]>
Commit | Line | Data |
---|---|---|
374ca955 | 1 | /* |
46f4442e A |
2 | ****************************************************************************** |
3 | * Copyright (C) 2003-2008, International Business Machines Corporation | |
4 | * and others. All Rights Reserved. | |
5 | ****************************************************************************** | |
6 | * | |
7 | * File ISLAMCAL.H | |
8 | * | |
9 | * Modification History: | |
10 | * | |
11 | * Date Name Description | |
12 | * 10/14/2003 srl ported from java IslamicCalendar | |
13 | ***************************************************************************** | |
14 | */ | |
374ca955 A |
15 | |
16 | #include "islamcal.h" | |
17 | ||
18 | #if !UCONFIG_NO_FORMATTING | |
19 | ||
46f4442e | 20 | #include "umutex.h" |
374ca955 A |
21 | #include <float.h> |
22 | #include "gregoimp.h" // Math | |
23 | #include "astro.h" // CalendarAstronomer | |
24 | #include "uhash.h" | |
25 | #include "ucln_in.h" | |
26 | ||
27 | static const UDate HIJRA_MILLIS = -42521587200000.0; // 7/16/622 AD 00:00 | |
28 | ||
29 | // Debugging | |
30 | #ifdef U_DEBUG_ISLAMCAL | |
31 | # include <stdio.h> | |
32 | # include <stdarg.h> | |
33 | static void debug_islamcal_loc(const char *f, int32_t l) | |
34 | { | |
46f4442e | 35 | fprintf(stderr, "%s:%d: ", f, l); |
374ca955 A |
36 | } |
37 | ||
38 | static void debug_islamcal_msg(const char *pat, ...) | |
39 | { | |
46f4442e A |
40 | va_list ap; |
41 | va_start(ap, pat); | |
42 | vfprintf(stderr, pat, ap); | |
43 | fflush(stderr); | |
374ca955 A |
44 | } |
45 | // must use double parens, i.e.: U_DEBUG_ISLAMCAL_MSG(("four is: %d",4)); | |
46 | #define U_DEBUG_ISLAMCAL_MSG(x) {debug_islamcal_loc(__FILE__,__LINE__);debug_islamcal_msg x;} | |
47 | #else | |
48 | #define U_DEBUG_ISLAMCAL_MSG(x) | |
49 | #endif | |
50 | ||
51 | ||
52 | // --- The cache -- | |
53 | // cache of months | |
54 | static UMTX astroLock = 0; // pod bay door lock | |
46f4442e A |
55 | static U_NAMESPACE_QUALIFIER CalendarCache *gMonthCache = NULL; |
56 | static U_NAMESPACE_QUALIFIER CalendarAstronomer *gIslamicCalendarAstro = NULL; | |
374ca955 A |
57 | |
58 | U_CDECL_BEGIN | |
59 | static UBool calendar_islamic_cleanup(void) { | |
60 | if (gMonthCache) { | |
61 | delete gMonthCache; | |
62 | gMonthCache = NULL; | |
63 | } | |
64 | if (gIslamicCalendarAstro) { | |
65 | delete gIslamicCalendarAstro; | |
66 | gIslamicCalendarAstro = NULL; | |
67 | } | |
68 | umtx_destroy(&astroLock); | |
69 | return TRUE; | |
70 | } | |
71 | U_CDECL_END | |
72 | ||
73 | U_NAMESPACE_BEGIN | |
74 | ||
75 | // Implementation of the IslamicCalendar class | |
76 | ||
77 | //------------------------------------------------------------------------- | |
78 | // Constructors... | |
79 | //------------------------------------------------------------------------- | |
80 | ||
81 | const char *IslamicCalendar::getType() const { | |
46f4442e A |
82 | if(civil==CIVIL) { |
83 | return "islamic-civil"; | |
84 | } else { | |
85 | return "islamic"; | |
86 | } | |
374ca955 A |
87 | } |
88 | ||
89 | Calendar* IslamicCalendar::clone() const { | |
46f4442e | 90 | return new IslamicCalendar(*this); |
374ca955 A |
91 | } |
92 | ||
93 | IslamicCalendar::IslamicCalendar(const Locale& aLocale, UErrorCode& success, ECivil beCivil) | |
46f4442e A |
94 | : Calendar(TimeZone::createDefault(), aLocale, success), |
95 | civil(beCivil) | |
374ca955 | 96 | { |
46f4442e | 97 | setTimeInMillis(getNow(), success); // Call this again now that the vtable is set up properly. |
374ca955 A |
98 | } |
99 | ||
100 | IslamicCalendar::IslamicCalendar(const IslamicCalendar& other) : Calendar(other), civil(other.civil) { | |
101 | } | |
102 | ||
103 | IslamicCalendar::~IslamicCalendar() | |
104 | { | |
105 | } | |
106 | ||
107 | /** | |
46f4442e A |
108 | * Determines whether this object uses the fixed-cycle Islamic civil calendar |
109 | * or an approximation of the religious, astronomical calendar. | |
110 | * | |
111 | * @param beCivil <code>true</code> to use the civil calendar, | |
112 | * <code>false</code> to use the astronomical calendar. | |
113 | * @draft ICU 2.4 | |
114 | */ | |
374ca955 A |
115 | void IslamicCalendar::setCivil(ECivil beCivil, UErrorCode &status) |
116 | { | |
46f4442e A |
117 | if (civil != beCivil) { |
118 | // The fields of the calendar will become invalid, because the calendar | |
119 | // rules are different | |
120 | UDate m = getTimeInMillis(status); | |
121 | civil = beCivil; | |
122 | clear(); | |
123 | setTimeInMillis(m, status); | |
124 | } | |
374ca955 | 125 | } |
46f4442e | 126 | |
374ca955 | 127 | /** |
46f4442e A |
128 | * Returns <code>true</code> if this object is using the fixed-cycle civil |
129 | * calendar, or <code>false</code> if using the religious, astronomical | |
130 | * calendar. | |
131 | * @draft ICU 2.4 | |
132 | */ | |
374ca955 | 133 | UBool IslamicCalendar::isCivil() { |
46f4442e | 134 | return (civil == CIVIL); |
374ca955 | 135 | } |
46f4442e | 136 | |
374ca955 A |
137 | //------------------------------------------------------------------------- |
138 | // Minimum / Maximum access functions | |
139 | //------------------------------------------------------------------------- | |
140 | ||
46f4442e A |
141 | // Note: Current IslamicCalendar implementation does not work |
142 | // well with negative years. | |
143 | ||
374ca955 | 144 | static const int32_t LIMITS[UCAL_FIELD_COUNT][4] = { |
46f4442e A |
145 | // Minimum Greatest Least Maximum |
146 | // Minimum Maximum | |
147 | { 0, 0, 0, 0}, // ERA | |
148 | { 1, 1, 5000000, 5000000}, // YEAR | |
149 | { 0, 0, 11, 11}, // MONTH | |
150 | { 1, 1, 50, 51}, // WEEK_OF_YEAR | |
151 | {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // WEEK_OF_MONTH | |
152 | { 1, 1, 29, 31}, // DAY_OF_MONTH (**** SB 30 ****) | |
153 | { 1, 1, 354, 355}, // DAY_OF_YEAR | |
154 | {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // DAY_OF_WEEK | |
155 | { -1, -1, 5, 5}, // DAY_OF_WEEK_IN_MONTH | |
156 | {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // AM_PM | |
157 | {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // HOUR | |
158 | {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // HOUR_OF_DAY | |
159 | {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // MINUTE | |
160 | {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // SECOND | |
161 | {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // MILLISECOND | |
162 | {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // ZONE_OFFSET | |
163 | {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // DST_OFFSET | |
164 | { 1, 1, 5000000, 5000000}, // YEAR_WOY | |
165 | {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // DOW_LOCAL | |
166 | { 1, 1, 5000000, 5000000}, // EXTENDED_YEAR | |
167 | {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // JULIAN_DAY | |
168 | {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // MILLISECONDS_IN_DAY | |
169 | {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // IS_LEAP_MONTH | |
374ca955 A |
170 | }; |
171 | ||
172 | /** | |
46f4442e A |
173 | * @draft ICU 2.4 |
174 | */ | |
374ca955 | 175 | int32_t IslamicCalendar::handleGetLimit(UCalendarDateFields field, ELimitType limitType) const { |
46f4442e | 176 | return LIMITS[field][limitType]; |
374ca955 A |
177 | } |
178 | ||
179 | //------------------------------------------------------------------------- | |
180 | // Assorted calculation utilities | |
181 | // | |
182 | ||
183 | /** | |
46f4442e A |
184 | * Determine whether a year is a leap year in the Islamic civil calendar |
185 | */ | |
374ca955 A |
186 | UBool IslamicCalendar::civilLeapYear(int32_t year) |
187 | { | |
46f4442e | 188 | return (14 + 11 * year) % 30 < 11; |
374ca955 | 189 | } |
46f4442e | 190 | |
374ca955 | 191 | /** |
46f4442e A |
192 | * Return the day # on which the given year starts. Days are counted |
193 | * from the Hijri epoch, origin 0. | |
194 | */ | |
374ca955 | 195 | int32_t IslamicCalendar::yearStart(int32_t year) { |
46f4442e A |
196 | if (civil == CIVIL) { |
197 | return (year-1)*354 + Math::floorDivide((3+11*year),30); | |
198 | } else { | |
199 | return trueMonthStart(12*(year-1)); | |
200 | } | |
374ca955 | 201 | } |
46f4442e | 202 | |
374ca955 | 203 | /** |
46f4442e A |
204 | * Return the day # on which the given month starts. Days are counted |
205 | * from the Hijri epoch, origin 0. | |
206 | * | |
207 | * @param year The hijri year | |
208 | * @param year The hijri month, 0-based | |
209 | */ | |
374ca955 | 210 | int32_t IslamicCalendar::monthStart(int32_t year, int32_t month) const { |
46f4442e A |
211 | if (civil == CIVIL) { |
212 | return (int32_t)uprv_ceil(29.5*month) | |
213 | + (year-1)*354 + (int32_t)Math::floorDivide((3+11*year),30); | |
214 | } else { | |
215 | return trueMonthStart(12*(year-1) + month); | |
216 | } | |
374ca955 | 217 | } |
46f4442e | 218 | |
374ca955 | 219 | /** |
46f4442e A |
220 | * Find the day number on which a particular month of the true/lunar |
221 | * Islamic calendar starts. | |
222 | * | |
223 | * @param month The month in question, origin 0 from the Hijri epoch | |
224 | * | |
225 | * @return The day number on which the given month starts. | |
226 | */ | |
374ca955 A |
227 | int32_t IslamicCalendar::trueMonthStart(int32_t month) const |
228 | { | |
46f4442e A |
229 | UErrorCode status = U_ZERO_ERROR; |
230 | int32_t start = CalendarCache::get(&gMonthCache, month, status); | |
231 | ||
232 | if (start==0) { | |
233 | // Make a guess at when the month started, using the average length | |
234 | UDate origin = HIJRA_MILLIS | |
235 | + uprv_floor(month * CalendarAstronomer::SYNODIC_MONTH - 1) * kOneDay; | |
236 | ||
237 | // moonAge will fail due to memory allocation error | |
238 | double age = moonAge(origin, status); | |
239 | if (U_FAILURE(status)) { | |
240 | goto trueMonthStartEnd; | |
241 | } | |
242 | ||
243 | if (age >= 0) { | |
244 | // The month has already started | |
245 | do { | |
246 | origin -= kOneDay; | |
247 | age = moonAge(origin, status); | |
248 | if (U_FAILURE(status)) { | |
249 | goto trueMonthStartEnd; | |
250 | } | |
251 | } while (age >= 0); | |
252 | } | |
253 | else { | |
254 | // Preceding month has not ended yet. | |
255 | do { | |
256 | origin += kOneDay; | |
257 | age = moonAge(origin, status); | |
258 | if (U_FAILURE(status)) { | |
259 | goto trueMonthStartEnd; | |
260 | } | |
261 | } while (age < 0); | |
262 | } | |
263 | start = (int32_t)Math::floorDivide((origin - HIJRA_MILLIS), (double)kOneDay) + 1; | |
264 | CalendarCache::put(&gMonthCache, month, start, status); | |
374ca955 | 265 | } |
46f4442e A |
266 | trueMonthStartEnd : |
267 | if(U_FAILURE(status)) { | |
268 | start = 0; | |
374ca955 | 269 | } |
46f4442e | 270 | return start; |
374ca955 A |
271 | } |
272 | ||
273 | /** | |
46f4442e A |
274 | * Return the "age" of the moon at the given time; this is the difference |
275 | * in ecliptic latitude between the moon and the sun. This method simply | |
276 | * calls CalendarAstronomer.moonAge, converts to degrees, | |
277 | * and adjusts the result to be in the range [-180, 180]. | |
278 | * | |
279 | * @param time The time at which the moon's age is desired, | |
280 | * in millis since 1/1/1970. | |
281 | */ | |
282 | double IslamicCalendar::moonAge(UDate time, UErrorCode &status) | |
374ca955 | 283 | { |
46f4442e A |
284 | double age = 0; |
285 | ||
286 | umtx_lock(&astroLock); | |
287 | if(gIslamicCalendarAstro == NULL) { | |
288 | gIslamicCalendarAstro = new CalendarAstronomer(); | |
289 | if (gIslamicCalendarAstro == NULL) { | |
290 | status = U_MEMORY_ALLOCATION_ERROR; | |
291 | return age; | |
292 | } | |
293 | ucln_i18n_registerCleanup(UCLN_I18N_ISLAMIC_CALENDAR, calendar_islamic_cleanup); | |
294 | } | |
295 | gIslamicCalendarAstro->setTime(time); | |
296 | age = gIslamicCalendarAstro->getMoonAge(); | |
297 | umtx_unlock(&astroLock); | |
298 | ||
299 | // Convert to degrees and normalize... | |
300 | age = age * 180 / CalendarAstronomer::PI; | |
301 | if (age > 180) { | |
302 | age = age - 360; | |
303 | } | |
304 | ||
305 | return age; | |
374ca955 A |
306 | } |
307 | ||
308 | //---------------------------------------------------------------------- | |
309 | // Calendar framework | |
310 | //---------------------------------------------------------------------- | |
311 | ||
312 | /** | |
46f4442e A |
313 | * Return the length (in days) of the given month. |
314 | * | |
315 | * @param year The hijri year | |
316 | * @param year The hijri month, 0-based | |
317 | * @draft ICU 2.4 | |
318 | */ | |
374ca955 A |
319 | int32_t IslamicCalendar::handleGetMonthLength(int32_t extendedYear, int32_t month) const { |
320 | ||
46f4442e A |
321 | int32_t length = 0; |
322 | ||
323 | if (civil == CIVIL) { | |
324 | length = 29 + (month+1) % 2; | |
325 | if (month == DHU_AL_HIJJAH && civilLeapYear(extendedYear)) { | |
326 | length++; | |
327 | } | |
328 | } else { | |
329 | month = 12*(extendedYear-1) + month; | |
330 | length = trueMonthStart(month+1) - trueMonthStart(month) ; | |
374ca955 | 331 | } |
46f4442e | 332 | return length; |
374ca955 A |
333 | } |
334 | ||
335 | /** | |
46f4442e A |
336 | * Return the number of days in the given Islamic year |
337 | * @draft ICU 2.4 | |
338 | */ | |
374ca955 | 339 | int32_t IslamicCalendar::handleGetYearLength(int32_t extendedYear) const { |
46f4442e A |
340 | if (civil == CIVIL) { |
341 | return 354 + (civilLeapYear(extendedYear) ? 1 : 0); | |
342 | } else { | |
343 | int32_t month = 12*(extendedYear-1); | |
344 | return (trueMonthStart(month + 12) - trueMonthStart(month)); | |
345 | } | |
374ca955 | 346 | } |
46f4442e | 347 | |
374ca955 A |
348 | //------------------------------------------------------------------------- |
349 | // Functions for converting from field values to milliseconds.... | |
350 | //------------------------------------------------------------------------- | |
351 | ||
352 | // Return JD of start of given month/year | |
353 | /** | |
46f4442e A |
354 | * @draft ICU 2.4 |
355 | */ | |
374ca955 | 356 | int32_t IslamicCalendar::handleComputeMonthStart(int32_t eyear, int32_t month, UBool /* useMonth */) const { |
46f4442e | 357 | return monthStart(eyear, month) + 1948439; |
374ca955 A |
358 | } |
359 | ||
360 | //------------------------------------------------------------------------- | |
361 | // Functions for converting from milliseconds to field values | |
362 | //------------------------------------------------------------------------- | |
363 | ||
46f4442e A |
364 | /** |
365 | * @draft ICU 2.4 | |
366 | */ | |
374ca955 A |
367 | int32_t IslamicCalendar::handleGetExtendedYear() { |
368 | int32_t year; | |
369 | if (newerField(UCAL_EXTENDED_YEAR, UCAL_YEAR) == UCAL_EXTENDED_YEAR) { | |
370 | year = internalGet(UCAL_EXTENDED_YEAR, 1); // Default to year 1 | |
371 | } else { | |
372 | year = internalGet(UCAL_YEAR, 1); // Default to year 1 | |
373 | } | |
374 | return year; | |
375 | } | |
376 | ||
377 | /** | |
46f4442e A |
378 | * Override Calendar to compute several fields specific to the Islamic |
379 | * calendar system. These are: | |
380 | * | |
381 | * <ul><li>ERA | |
382 | * <li>YEAR | |
383 | * <li>MONTH | |
384 | * <li>DAY_OF_MONTH | |
385 | * <li>DAY_OF_YEAR | |
386 | * <li>EXTENDED_YEAR</ul> | |
387 | * | |
388 | * The DAY_OF_WEEK and DOW_LOCAL fields are already set when this | |
389 | * method is called. The getGregorianXxx() methods return Gregorian | |
390 | * calendar equivalents for the given Julian day. | |
391 | * @draft ICU 2.4 | |
392 | */ | |
393 | void IslamicCalendar::handleComputeFields(int32_t julianDay, UErrorCode &status) { | |
374ca955 A |
394 | int32_t year, month, dayOfMonth, dayOfYear; |
395 | UDate startDate; | |
396 | int32_t days = julianDay - 1948440; | |
46f4442e | 397 | |
374ca955 A |
398 | if (civil == CIVIL) { |
399 | // Use the civil calendar approximation, which is just arithmetic | |
400 | year = (int)Math::floorDivide( (double)(30 * days + 10646) , 10631.0 ); | |
401 | month = (int32_t)uprv_ceil((days - 29 - yearStart(year)) / 29.5 ); | |
402 | month = month<11?month:11; | |
403 | startDate = monthStart(year, month); | |
404 | } else { | |
405 | // Guess at the number of elapsed full months since the epoch | |
406 | int32_t months = (int32_t)uprv_floor((double)days / CalendarAstronomer::SYNODIC_MONTH); | |
407 | ||
408 | startDate = uprv_floor(months * CalendarAstronomer::SYNODIC_MONTH - 1); | |
409 | ||
46f4442e A |
410 | double age = moonAge(internalGetTime(), status); |
411 | if (U_FAILURE(status)) { | |
412 | status = U_MEMORY_ALLOCATION_ERROR; | |
413 | return; | |
414 | } | |
415 | if ( days - startDate >= 28 && age > 0) { | |
374ca955 A |
416 | // If we're near the end of the month, assume next month and search backwards |
417 | months++; | |
418 | } | |
419 | ||
420 | // Find out the last time that the new moon was actually visible at this longitude | |
421 | // This returns midnight the night that the moon was visible at sunset. | |
422 | while ((startDate = trueMonthStart(months)) > days) { | |
423 | // If it was after the date in question, back up a month and try again | |
424 | months--; | |
425 | } | |
46f4442e | 426 | |
374ca955 A |
427 | year = months / 12 + 1; |
428 | month = months % 12; | |
429 | } | |
46f4442e | 430 | |
374ca955 A |
431 | dayOfMonth = (days - monthStart(year, month)) + 1; |
432 | ||
433 | // Now figure out the day of the year. | |
434 | dayOfYear = (days - monthStart(year, 0) + 1); | |
435 | ||
436 | internalSet(UCAL_ERA, 0); | |
437 | internalSet(UCAL_YEAR, year); | |
438 | internalSet(UCAL_EXTENDED_YEAR, year); | |
439 | internalSet(UCAL_MONTH, month); | |
440 | internalSet(UCAL_DAY_OF_MONTH, dayOfMonth); | |
441 | internalSet(UCAL_DAY_OF_YEAR, dayOfYear); | |
442 | } | |
443 | ||
444 | UBool | |
445 | IslamicCalendar::inDaylightTime(UErrorCode& status) const | |
446 | { | |
46f4442e A |
447 | // copied from GregorianCalendar |
448 | if (U_FAILURE(status) || (&(getTimeZone()) == NULL && !getTimeZone().useDaylightTime())) | |
449 | return FALSE; | |
374ca955 A |
450 | |
451 | // Force an update of the state of the Calendar. | |
46f4442e | 452 | ((IslamicCalendar*)this)->complete(status); // cast away const |
374ca955 | 453 | |
46f4442e | 454 | return (UBool)(U_SUCCESS(status) ? (internalGet(UCAL_DST_OFFSET) != 0) : FALSE); |
374ca955 A |
455 | } |
456 | ||
457 | // default century | |
458 | const UDate IslamicCalendar::fgSystemDefaultCentury = DBL_MIN; | |
459 | const int32_t IslamicCalendar::fgSystemDefaultCenturyYear = -1; | |
460 | ||
461 | UDate IslamicCalendar::fgSystemDefaultCenturyStart = DBL_MIN; | |
462 | int32_t IslamicCalendar::fgSystemDefaultCenturyStartYear = -1; | |
463 | ||
464 | ||
465 | UBool IslamicCalendar::haveDefaultCentury() const | |
466 | { | |
46f4442e | 467 | return TRUE; |
374ca955 A |
468 | } |
469 | ||
470 | UDate IslamicCalendar::defaultCenturyStart() const | |
471 | { | |
46f4442e | 472 | return internalGetDefaultCenturyStart(); |
374ca955 A |
473 | } |
474 | ||
475 | int32_t IslamicCalendar::defaultCenturyStartYear() const | |
476 | { | |
46f4442e | 477 | return internalGetDefaultCenturyStartYear(); |
374ca955 A |
478 | } |
479 | ||
480 | UDate | |
481 | IslamicCalendar::internalGetDefaultCenturyStart() const | |
482 | { | |
46f4442e A |
483 | // lazy-evaluate systemDefaultCenturyStart |
484 | UBool needsUpdate; | |
485 | UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate); | |
486 | ||
487 | if (needsUpdate) { | |
488 | initializeSystemDefaultCentury(); | |
489 | } | |
490 | ||
491 | // use defaultCenturyStart unless it's the flag value; | |
492 | // then use systemDefaultCenturyStart | |
493 | ||
494 | return fgSystemDefaultCenturyStart; | |
374ca955 A |
495 | } |
496 | ||
497 | int32_t | |
498 | IslamicCalendar::internalGetDefaultCenturyStartYear() const | |
499 | { | |
46f4442e A |
500 | // lazy-evaluate systemDefaultCenturyStartYear |
501 | UBool needsUpdate; | |
502 | UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate); | |
503 | ||
504 | if (needsUpdate) { | |
505 | initializeSystemDefaultCentury(); | |
506 | } | |
507 | ||
508 | // use defaultCenturyStart unless it's the flag value; | |
509 | // then use systemDefaultCenturyStartYear | |
510 | ||
511 | return fgSystemDefaultCenturyStartYear; | |
374ca955 A |
512 | } |
513 | ||
514 | void | |
515 | IslamicCalendar::initializeSystemDefaultCentury() | |
516 | { | |
46f4442e A |
517 | // initialize systemDefaultCentury and systemDefaultCenturyYear based |
518 | // on the current time. They'll be set to 80 years before | |
519 | // the current time. | |
520 | // No point in locking as it should be idempotent. | |
521 | if (fgSystemDefaultCenturyStart == fgSystemDefaultCentury) | |
374ca955 | 522 | { |
46f4442e A |
523 | UErrorCode status = U_ZERO_ERROR; |
524 | IslamicCalendar calendar(Locale("@calendar=islamic-civil"),status); | |
525 | if (U_SUCCESS(status)) | |
526 | { | |
527 | calendar.setTime(Calendar::getNow(), status); | |
528 | calendar.add(UCAL_YEAR, -80, status); | |
529 | UDate newStart = calendar.getTime(status); | |
530 | int32_t newYear = calendar.get(UCAL_YEAR, status); | |
531 | { | |
532 | umtx_lock(NULL); | |
533 | fgSystemDefaultCenturyStart = newStart; | |
534 | fgSystemDefaultCenturyStartYear = newYear; | |
535 | umtx_unlock(NULL); | |
536 | } | |
537 | } | |
538 | // We have no recourse upon failure unless we want to propagate the failure | |
539 | // out. | |
374ca955 | 540 | } |
374ca955 A |
541 | } |
542 | ||
543 | UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IslamicCalendar) | |
544 | ||
545 | U_NAMESPACE_END | |
546 | ||
547 | #endif | |
548 |