1 /******************************************************************************* 2 3 copyright: Copyright (c) 2005 John Chapman. All rights reserved 4 5 license: BSD style: $(LICENSE) 6 7 version: Mid 2005: Initial release 8 Apr 2007: reshaped 9 10 author: John Chapman, Kris 11 12 ******************************************************************************/ 13 14 module tango.time.chrono.Hijri; 15 16 private import tango.time.chrono.Calendar; 17 18 19 /** 20 * $(ANCHOR _Hijri) 21 * Represents the Hijri calendar. 22 */ 23 public class Hijri : Calendar { 24 25 private __gshared immutable uint[] DAYS_TO_MONTH = [ 0, 30, 59, 89, 118, 148, 177, 207, 236, 266, 295, 325, 355 ]; 26 27 /** 28 * Represents the current era. 29 */ 30 public __gshared immutable uint HIJRI_ERA = 1; 31 32 /** 33 * Overridden. Returns a Time value set to the specified date and time in the specified _era. 34 * Params: 35 * year = An integer representing the _year. 36 * month = An integer representing the _month. 37 * day = An integer representing the _day. 38 * hour = An integer representing the _hour. 39 * minute = An integer representing the _minute. 40 * second = An integer representing the _second. 41 * millisecond = An integer representing the _millisecond. 42 * era = An integer representing the _era. 43 * Returns: A Time set to the specified date and time. 44 */ 45 public override const Time toTime(uint year, uint month, uint day, uint hour, uint minute, uint second, uint millisecond, uint era) { 46 return Time((daysSinceJan1(year, month, day) - 1) * TimeSpan.TicksPerDay + getTimeTicks(hour, minute, second)) + TimeSpan.fromMillis(millisecond); 47 } 48 49 /** 50 * Overridden. Returns the day of the week in the specified Time. 51 * Params: time = A Time value. 52 * Returns: A DayOfWeek value representing the day of the week of time. 53 */ 54 public override const DayOfWeek getDayOfWeek(const(Time) time) { 55 return cast(DayOfWeek) (cast(uint) (time.ticks / TimeSpan.TicksPerDay + 1) % 7); 56 } 57 58 /** 59 * Overridden. Returns the day of the month in the specified Time. 60 * Params: time = A Time value. 61 * Returns: An integer representing the day of the month of time. 62 */ 63 public override const uint getDayOfMonth(const(Time) time) { 64 return extractPart(time.ticks, DatePart.Day); 65 } 66 67 /** 68 * Overridden. Returns the day of the year in the specified Time. 69 * Params: time = A Time value. 70 * Returns: An integer representing the day of the year of time. 71 */ 72 public override const uint getDayOfYear(const(Time) time) { 73 return extractPart(time.ticks, DatePart.DayOfYear); 74 } 75 76 /** 77 * Overridden. Returns the day of the year in the specified Time. 78 * Params: time = A Time value. 79 * Returns: An integer representing the day of the year of time. 80 */ 81 public override const uint getMonth(const(Time) time) { 82 return extractPart(time.ticks, DatePart.Month); 83 } 84 85 /** 86 * Overridden. Returns the year in the specified Time. 87 * Params: time = A Time value. 88 * Returns: An integer representing the year in time. 89 */ 90 public override const uint getYear(const(Time) time) { 91 return extractPart(time.ticks, DatePart.Year); 92 } 93 94 /** 95 * Overridden. Returns the era in the specified Time. 96 * Params: time = A Time value. 97 * Returns: An integer representing the ear in time. 98 */ 99 public override const uint getEra(const(Time) time) { 100 return HIJRI_ERA; 101 } 102 103 /** 104 * Overridden. Returns the number of days in the specified _year and _month of the specified _era. 105 * Params: 106 * year = An integer representing the _year. 107 * month = An integer representing the _month. 108 * era = An integer representing the _era. 109 * Returns: The number of days in the specified _year and _month of the specified _era. 110 */ 111 public override const uint getDaysInMonth(uint year, uint month, uint era) { 112 if (month == 12) 113 return isLeapYear(year, CURRENT_ERA) ? 30 : 29; 114 return (month % 2 == 1) ? 30 : 29; 115 } 116 117 /** 118 * Overridden. Returns the number of days in the specified _year of the specified _era. 119 * Params: 120 * year = An integer representing the _year. 121 * era = An integer representing the _era. 122 * Returns: The number of days in the specified _year in the specified _era. 123 */ 124 public override const uint getDaysInYear(uint year, uint era) { 125 return isLeapYear(year, era) ? 355 : 354; 126 } 127 128 /** 129 * Overridden. Returns the number of months in the specified _year of the specified _era. 130 * Params: 131 * year = An integer representing the _year. 132 * era = An integer representing the _era. 133 * Returns: The number of months in the specified _year in the specified _era. 134 */ 135 public override const uint getMonthsInYear(uint year, uint era) { 136 return 12; 137 } 138 139 /** 140 * Overridden. Indicates whether the specified _year in the specified _era is a leap _year. 141 * Params: year = An integer representing the _year. 142 * Params: era = An integer representing the _era. 143 * Returns: true is the specified _year is a leap _year; otherwise, false. 144 */ 145 public override const bool isLeapYear(uint year, uint era) { 146 return (14 + 11 * year) % 30 < 11; 147 } 148 149 /** 150 * $(I Property.) Overridden. Retrieves the list of eras in the current calendar. 151 * Returns: An integer array representing the eras in the current calendar. 152 */ 153 public override const uint[] eras() { 154 auto tmp = [HIJRI_ERA]; 155 return tmp.dup; 156 } 157 158 /** 159 * $(I Property.) Overridden. Retrieves the identifier associated with the current calendar. 160 * Returns: An integer representing the identifier of the current calendar. 161 */ 162 public override const uint id() { 163 return HIJRI; 164 } 165 166 private const long daysToYear(uint year) { 167 int cycle = ((year - 1) / 30) * 30; 168 int remaining = year - cycle - 1; 169 long days = ((cycle * 10631L) / 30L) + 227013L; 170 while (remaining > 0) { 171 days += 354 + (isLeapYear(remaining, CURRENT_ERA) ? 1 : 0); 172 remaining--; 173 } 174 return days; 175 } 176 177 private const long daysSinceJan1(uint year, uint month, uint day) { 178 return cast(long)(daysToYear(year) + DAYS_TO_MONTH[month - 1] + day); 179 } 180 181 private const int extractPart(long ticks, DatePart part) { 182 long days = TimeSpan(ticks).days + 1; 183 int year = cast(int)(((days - 227013) * 30) / 10631) + 1; 184 long daysUpToYear = daysToYear(year); 185 long daysInYear = getDaysInYear(year, CURRENT_ERA); 186 if (days < daysUpToYear) { 187 daysUpToYear -= daysInYear; 188 year--; 189 } 190 else if (days == daysUpToYear) { 191 year--; 192 daysUpToYear -= getDaysInYear(year, CURRENT_ERA); 193 } 194 else if (days > daysUpToYear + daysInYear) { 195 daysUpToYear += daysInYear; 196 year++; 197 } 198 199 if (part == DatePart.Year) 200 return year; 201 202 days -= daysUpToYear; 203 if (part == DatePart.DayOfYear) 204 return cast(int)days; 205 206 int month = 1; 207 while (month <= 12 && days > DAYS_TO_MONTH[month - 1]) 208 month++; 209 month--; 210 if (part == DatePart.Month) 211 return month; 212 213 return cast(int)(days - DAYS_TO_MONTH[month - 1]); 214 } 215 216 } 217