comparison tango/tango/time/chrono/Hebrew.d @ 132:1700239cab2e trunk

[svn r136] MAJOR UNSTABLE UPDATE!!! Initial commit after moving to Tango instead of Phobos. Lots of bugfixes... This build is not suitable for most things.
author lindquist
date Fri, 11 Jan 2008 17:57:40 +0100
parents
children
comparison
equal deleted inserted replaced
131:5825d48b27d1 132:1700239cab2e
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, snoyberg
11
12 ******************************************************************************/
13
14 module tango.time.chrono.Hebrew;
15
16 private import tango.core.Exception;
17
18 private import tango.time.chrono.Calendar;
19
20
21
22 /**
23 * $(ANCHOR _Hebrew)
24 * Represents the Hebrew calendar.
25 */
26 public class Hebrew : Calendar {
27
28 private const uint[14][7] MonthDays = [
29 // month // year type
30 [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
31 [ 0, 30, 29, 29, 29, 30, 29, 0, 30, 29, 30, 29, 30, 29 ], // 1
32 [ 0, 30, 29, 30, 29, 30, 29, 0, 30, 29, 30, 29, 30, 29 ], // 2
33 [ 0, 30, 30, 30, 29, 30, 29, 0, 30, 29, 30, 29, 30, 29 ], // 3
34 [ 0, 30, 29, 29, 29, 30, 30, 29, 30, 29, 30, 29, 30, 29 ], // 4
35 [ 0, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30, 29, 30, 29 ], // 5
36 [ 0, 30, 30, 30, 29, 30, 30, 29, 30, 29, 30, 29, 30, 29 ] // 6
37 ];
38
39 private const uint YearOfOneAD = 3760;
40 private const uint DaysToOneAD = cast(int)(YearOfOneAD * 365.2735);
41
42 private const uint PartsPerHour = 1080;
43 private const uint PartsPerDay = 24 * PartsPerHour;
44 private const uint DaysPerMonth = 29;
45 private const uint DaysPerMonthFraction = 12 * PartsPerHour + 793;
46 private const uint PartsPerMonth = DaysPerMonth * PartsPerDay + DaysPerMonthFraction;
47 private const uint FirstNewMoon = 11 * PartsPerHour + 204;
48
49 private uint minYear_ = YearOfOneAD + 1583;
50 private uint maxYear_ = YearOfOneAD + 2240;
51
52 /**
53 * Represents the current era.
54 */
55 public const uint HEBREW_ERA = 1;
56
57 /**
58 * Overridden. Returns a Time value set to the specified date and time in the specified _era.
59 * Params:
60 * year = An integer representing the _year.
61 * month = An integer representing the _month.
62 * day = An integer representing the _day.
63 * hour = An integer representing the _hour.
64 * minute = An integer representing the _minute.
65 * second = An integer representing the _second.
66 * millisecond = An integer representing the _millisecond.
67 * era = An integer representing the _era.
68 * Returns: A Time set to the specified date and time.
69 */
70 public override Time toTime(uint year, uint month, uint day, uint hour, uint minute, uint second, uint millisecond, uint era) {
71 checkYear(year, era);
72 return getGregorianTime(year, month, day, hour, minute, second, millisecond);
73 }
74
75 /**
76 * Overridden. Returns the day of the week in the specified Time.
77 * Params: time = A Time value.
78 * Returns: A DayOfWeek value representing the day of the week of time.
79 */
80 public override DayOfWeek getDayOfWeek(Time time) {
81 return cast(DayOfWeek) cast(uint) ((time.ticks / TimeSpan.TicksPerDay + 1) % 7);
82 }
83
84 /**
85 * Overridden. Returns the day of the month in the specified Time.
86 * Params: time = A Time value.
87 * Returns: An integer representing the day of the month of time.
88 */
89 public override uint getDayOfMonth(Time time) {
90 auto year = getYear(time);
91 auto yearType = getYearType(year);
92 auto days = getStartOfYear(year) - DaysToOneAD;
93 auto day = cast(int)(time.ticks / TimeSpan.TicksPerDay) - days;
94 uint n;
95 while (n < 12 && day >= MonthDays[yearType][n + 1]) {
96 day -= MonthDays[yearType][n + 1];
97 n++;
98 }
99 return day + 1;
100 }
101
102 /**
103 * Overridden. Returns the day of the year in the specified Time.
104 * Params: time = A Time value.
105 * Returns: An integer representing the day of the year of time.
106 */
107 public override uint getDayOfYear(Time time) {
108 auto year = getYear(time);
109 auto days = getStartOfYear(year) - DaysToOneAD;
110 return (cast(uint)(time.ticks / TimeSpan.TicksPerDay) - days) + 1;
111 }
112
113 /**
114 * Overridden. Returns the month in the specified Time.
115 * Params: time = A Time value.
116 * Returns: An integer representing the month in time.
117 */
118 public override uint getMonth(Time time) {
119 auto year = getYear(time);
120 auto yearType = getYearType(year);
121 auto days = getStartOfYear(year) - DaysToOneAD;
122 auto day = cast(int)(time.ticks / TimeSpan.TicksPerDay) - days;
123 uint n;
124 while (n < 12 && day >= MonthDays[yearType][n + 1]) {
125 day -= MonthDays[yearType][n + 1];
126 n++;
127 }
128 return n + 1;
129 }
130
131 /**
132 * Overridden. Returns the year in the specified Time.
133 * Params: time = A Time value.
134 * Returns: An integer representing the year in time.
135 */
136 public override uint getYear(Time time) {
137 auto day = cast(uint)(time.ticks / TimeSpan.TicksPerDay) + DaysToOneAD;
138 auto low = minYear_, high = maxYear_;
139 // Perform a binary search.
140 while (low <= high) {
141 auto mid = low + (high - low) / 2;
142 auto startDay = getStartOfYear(mid);
143 if (day < startDay)
144 high = mid - 1;
145 else if (day >= startDay && day < getStartOfYear(mid + 1))
146 return mid;
147 else
148 low = mid + 1;
149 }
150 return low;
151 }
152
153 /**
154 * Overridden. Returns the era in the specified Time.
155 * Params: time = A Time value.
156 * Returns: An integer representing the ear in time.
157 */
158 public override uint getEra(Time time) {
159 return HEBREW_ERA;
160 }
161
162 /**
163 * Overridden. Returns the number of days in the specified _year and _month of the specified _era.
164 * Params:
165 * year = An integer representing the _year.
166 * month = An integer representing the _month.
167 * era = An integer representing the _era.
168 * Returns: The number of days in the specified _year and _month of the specified _era.
169 */
170 public override uint getDaysInMonth(uint year, uint month, uint era) {
171 checkYear(year, era);
172 return MonthDays[getYearType(year)][month];
173 }
174
175 /**
176 * Overridden. Returns the number of days in the specified _year of the specified _era.
177 * Params:
178 * year = An integer representing the _year.
179 * era = An integer representing the _era.
180 * Returns: The number of days in the specified _year in the specified _era.
181 */
182 public override uint getDaysInYear(uint year, uint era) {
183 return getStartOfYear(year + 1) - getStartOfYear(year);
184 }
185
186 /**
187 * Overridden. Returns the number of months in the specified _year of the specified _era.
188 * Params:
189 * year = An integer representing the _year.
190 * era = An integer representing the _era.
191 * Returns: The number of months in the specified _year in the specified _era.
192 */
193 public override uint getMonthsInYear(uint year, uint era) {
194 return isLeapYear(year, era) ? 13 : 12;
195 }
196
197 /**
198 * Overridden. Indicates whether the specified _year in the specified _era is a leap _year.
199 * Params: year = An integer representing the _year.
200 * Params: era = An integer representing the _era.
201 * Returns: true is the specified _year is a leap _year; otherwise, false.
202 */
203 public override bool isLeapYear(uint year, uint era) {
204 checkYear(year, era);
205 // true if year % 19 == 0, 3, 6, 8, 11, 14, 17
206 return ((7 * year + 1) % 19) < 7;
207 }
208
209 /**
210 * $(I Property.) Overridden. Retrieves the list of eras in the current calendar.
211 * Returns: An integer array representing the eras in the current calendar.
212 */
213 public override uint[] eras() {
214 auto tmp = [HEBREW_ERA];
215 return tmp.dup;
216 }
217
218 /**
219 * $(I Property.) Overridden. Retrieves the identifier associated with the current calendar.
220 * Returns: An integer representing the identifier of the current calendar.
221 */
222 public override uint id() {
223 return HEBREW;
224 }
225
226 private void checkYear(uint year, uint era) {
227 if ((era != CURRENT_ERA && era != HEBREW_ERA) || (year > maxYear_ || year < minYear_))
228 throw new IllegalArgumentException("Value was out of range.");
229 }
230
231 private uint getYearType(uint year) {
232 int yearLength = getStartOfYear(year + 1) - getStartOfYear(year);
233 if (yearLength > 380)
234 yearLength -= 30;
235 switch (yearLength) {
236 case 353:
237 // "deficient"
238 return 1;
239 case 383:
240 // "deficient" leap
241 return 4;
242 case 354:
243 // "normal"
244 return 2;
245 case 384:
246 // "normal" leap
247 return 5;
248 case 355:
249 // "complete"
250 return 3;
251 case 385:
252 // "complete" leap
253 return 6;
254 default:
255 break;
256 }
257 // Satisfies -w
258 throw new IllegalArgumentException("Value was not valid.");
259 }
260
261 private uint getStartOfYear(uint year) {
262 auto months = (235 * year - 234) / 19;
263 auto fraction = months * DaysPerMonthFraction + FirstNewMoon;
264 auto day = months * 29 + (fraction / PartsPerDay);
265 fraction %= PartsPerDay;
266
267 auto dayOfWeek = day % 7;
268 if (dayOfWeek == 2 || dayOfWeek == 4 || dayOfWeek == 6) {
269 day++;
270 dayOfWeek = day % 7;
271 }
272 if (dayOfWeek == 1 && fraction > 15 * PartsPerHour + 204 && !isLeapYear(year, CURRENT_ERA))
273 day += 2;
274 else if (dayOfWeek == 0 && fraction > 21 * PartsPerHour + 589 && isLeapYear(year, CURRENT_ERA))
275 day++;
276 return day;
277 }
278
279 private Time getGregorianTime(uint year, uint month, uint day, uint hour, uint minute, uint second, uint millisecond) {
280 auto yearType = getYearType(year);
281 auto days = getStartOfYear(year) - DaysToOneAD + day - 1;
282 for (int i = 1; i <= month; i++)
283 days += MonthDays[yearType][i - 1];
284 return Time((days * TimeSpan.TicksPerDay) + getTimeTicks(hour, minute, second)) + TimeSpan.millis(millisecond);
285 }
286
287 }
288