X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/46f4442e9a5a4f3b98b7c1083586332f6a8a99a4..efa1e6592fb03ce23b15276b2b91d885a3ee7da5:/icuSources/i18n/islamcal.cpp?ds=sidebyside diff --git a/icuSources/i18n/islamcal.cpp b/icuSources/i18n/islamcal.cpp index 47669d39..6d553787 100644 --- a/icuSources/i18n/islamcal.cpp +++ b/icuSources/i18n/islamcal.cpp @@ -1,6 +1,6 @@ /* ****************************************************************************** -* Copyright (C) 2003-2008, International Business Machines Corporation +* Copyright (C) 2003-2012, International Business Machines Corporation * and others. All Rights Reserved. ****************************************************************************** * @@ -51,9 +51,9 @@ static void debug_islamcal_msg(const char *pat, ...) // --- The cache -- // cache of months -static UMTX astroLock = 0; // pod bay door lock -static U_NAMESPACE_QUALIFIER CalendarCache *gMonthCache = NULL; -static U_NAMESPACE_QUALIFIER CalendarAstronomer *gIslamicCalendarAstro = NULL; +static UMutex astroLock = U_MUTEX_INITIALIZER; // pod bay door lock +static icu::CalendarCache *gMonthCache = NULL; +static icu::CalendarAstronomer *gIslamicCalendarAstro = NULL; U_CDECL_BEGIN static UBool calendar_islamic_cleanup(void) { @@ -65,7 +65,6 @@ static UBool calendar_islamic_cleanup(void) { delete gIslamicCalendarAstro; gIslamicCalendarAstro = NULL; } - umtx_destroy(&astroLock); return TRUE; } U_CDECL_END @@ -141,6 +140,10 @@ UBool IslamicCalendar::isCivil() { // Note: Current IslamicCalendar implementation does not work // well with negative years. +// TODO: In some cases the current ICU Islamic calendar implementation shows +// a month as having 31 days. Since date parsing now uses range checks based +// on the table below, we need to change the range for last day of month to +// include 31 as a workaround until the implementation is fixed. static const int32_t LIMITS[UCAL_FIELD_COUNT][4] = { // Minimum Greatest Least Maximum // Minimum Maximum @@ -149,7 +152,7 @@ static const int32_t LIMITS[UCAL_FIELD_COUNT][4] = { { 0, 0, 11, 11}, // MONTH { 1, 1, 50, 51}, // WEEK_OF_YEAR {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // WEEK_OF_MONTH - { 1, 1, 29, 31}, // DAY_OF_MONTH (**** SB 30 ****) + { 1, 1, 29, 31}, // DAY_OF_MONTH - 31 to workaround for cal implementation bug, should be 30 { 1, 1, 354, 355}, // DAY_OF_YEAR {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // DAY_OF_WEEK { -1, -1, 5, 5}, // DAY_OF_WEEK_IN_MONTH @@ -194,7 +197,7 @@ UBool IslamicCalendar::civilLeapYear(int32_t year) */ int32_t IslamicCalendar::yearStart(int32_t year) { if (civil == CIVIL) { - return (year-1)*354 + Math::floorDivide((3+11*year),30); + return (year-1)*354 + ClockMath::floorDivide((3+11*year),30); } else { return trueMonthStart(12*(year-1)); } @@ -210,7 +213,7 @@ int32_t IslamicCalendar::yearStart(int32_t year) { int32_t IslamicCalendar::monthStart(int32_t year, int32_t month) const { if (civil == CIVIL) { return (int32_t)uprv_ceil(29.5*month) - + (year-1)*354 + (int32_t)Math::floorDivide((3+11*year),30); + + (year-1)*354 + (int32_t)ClockMath::floorDivide((3+11*year),30); } else { return trueMonthStart(12*(year-1) + month); } @@ -232,7 +235,7 @@ int32_t IslamicCalendar::trueMonthStart(int32_t month) const if (start==0) { // Make a guess at when the month started, using the average length UDate origin = HIJRA_MILLIS - + uprv_floor(month * CalendarAstronomer::SYNODIC_MONTH - 1) * kOneDay; + + uprv_floor(month * CalendarAstronomer::SYNODIC_MONTH) * kOneDay; // moonAge will fail due to memory allocation error double age = moonAge(origin, status); @@ -260,7 +263,7 @@ int32_t IslamicCalendar::trueMonthStart(int32_t month) const } } while (age < 0); } - start = (int32_t)Math::floorDivide((origin - HIJRA_MILLIS), (double)kOneDay) + 1; + start = (int32_t)ClockMath::floorDivide((origin - HIJRA_MILLIS), (double)kOneDay) + 1; CalendarCache::put(&gMonthCache, month, start, status); } trueMonthStartEnd : @@ -397,7 +400,7 @@ void IslamicCalendar::handleComputeFields(int32_t julianDay, UErrorCode &status) if (civil == CIVIL) { // Use the civil calendar approximation, which is just arithmetic - year = (int)Math::floorDivide( (double)(30 * days + 10646) , 10631.0 ); + year = (int)ClockMath::floorDivide( (double)(30 * days + 10646) , 10631.0 ); month = (int32_t)uprv_ceil((days - 29 - yearStart(year)) / 29.5 ); month = month<11?month:11; startDate = monthStart(year, month); @@ -405,14 +408,14 @@ void IslamicCalendar::handleComputeFields(int32_t julianDay, UErrorCode &status) // Guess at the number of elapsed full months since the epoch int32_t months = (int32_t)uprv_floor((double)days / CalendarAstronomer::SYNODIC_MONTH); - startDate = uprv_floor(months * CalendarAstronomer::SYNODIC_MONTH - 1); + startDate = uprv_floor(months * CalendarAstronomer::SYNODIC_MONTH); double age = moonAge(internalGetTime(), status); if (U_FAILURE(status)) { status = U_MEMORY_ALLOCATION_ERROR; return; } - if ( days - startDate >= 28 && age > 0) { + if ( days - startDate >= 25 && age > 0) { // If we're near the end of the month, assume next month and search backwards months++; } @@ -517,27 +520,24 @@ IslamicCalendar::initializeSystemDefaultCentury() // initialize systemDefaultCentury and systemDefaultCenturyYear based // on the current time. They'll be set to 80 years before // the current time. - // No point in locking as it should be idempotent. - if (fgSystemDefaultCenturyStart == fgSystemDefaultCentury) + UErrorCode status = U_ZERO_ERROR; + IslamicCalendar calendar(Locale("@calendar=islamic-civil"),status); + if (U_SUCCESS(status)) { - UErrorCode status = U_ZERO_ERROR; - IslamicCalendar calendar(Locale("@calendar=islamic-civil"),status); - if (U_SUCCESS(status)) + calendar.setTime(Calendar::getNow(), status); + calendar.add(UCAL_YEAR, -80, status); + UDate newStart = calendar.getTime(status); + int32_t newYear = calendar.get(UCAL_YEAR, status); + umtx_lock(NULL); + if (fgSystemDefaultCenturyStart == fgSystemDefaultCentury) { - calendar.setTime(Calendar::getNow(), status); - calendar.add(UCAL_YEAR, -80, status); - UDate newStart = calendar.getTime(status); - int32_t newYear = calendar.get(UCAL_YEAR, status); - { - umtx_lock(NULL); - fgSystemDefaultCenturyStart = newStart; - fgSystemDefaultCenturyStartYear = newYear; - umtx_unlock(NULL); - } + fgSystemDefaultCenturyStartYear = newYear; + fgSystemDefaultCenturyStart = newStart; } - // We have no recourse upon failure unless we want to propagate the failure - // out. + umtx_unlock(NULL); } + // We have no recourse upon failure unless we want to propagate the failure + // out. } UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IslamicCalendar)