]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/i18n/gregocal.cpp
ICU-57149.0.1.tar.gz
[apple/icu.git] / icuSources / i18n / gregocal.cpp
index a3e6423142805ae4df0569076c018fb5dd7f6ff9..3dcd90831157a844112dc6f493a8d37a5e97302b 100644 (file)
@@ -1,7 +1,7 @@
 /*
 *******************************************************************************
-* Copyright (C) 1997-2008, International Business Machines Corporation and    *
-* others. All Rights Reserved.                                                *
+* Copyright (C) 1997-2016, International Business Machines Corporation and
+* others. All Rights Reserved.
 *******************************************************************************
 *
 * File GREGOCAL.CPP
@@ -150,7 +150,7 @@ static const UDate kPapalCutover = (2299161.0 - kEpochStartAsJulianDay) * U_MILL
 // -------------------------------------
 
 GregorianCalendar::GregorianCalendar(UErrorCode& status)
-:   Calendar(TimeZone::createDefault(), Locale::getDefault(), status),
+:   Calendar(status),
 fGregorianCutover(kPapalCutover),
 fCutoverJulianDay(kCutoverJulianDay), fNormalizedGregorianCutover(fGregorianCutover), fGregorianCutoverYear(1582),
 fIsGregorian(TRUE), fInvertGregorian(FALSE)
@@ -330,7 +330,7 @@ GregorianCalendar::setGregorianChange(UDate date, UErrorCode& status)
     // normalized cutover is in pure date milliseconds; it contains no time
     // of day or timezone component, and it used to compare against other
     // pure date values.
-    int32_t cutoverDay = (int32_t)Math::floorDivide(fGregorianCutover, (double)kOneDay);
+    int32_t cutoverDay = (int32_t)ClockMath::floorDivide(fGregorianCutover, (double)kOneDay);
     fNormalizedGregorianCutover = cutoverDay * kOneDay;
 
     // Handle the rare case of numeric overflow.  If the user specifies a
@@ -364,7 +364,7 @@ GregorianCalendar::setGregorianChange(UDate date, UErrorCode& status)
 
 
 void GregorianCalendar::handleComputeFields(int32_t julianDay, UErrorCode& status) {
-    int32_t eyear, month, dayOfMonth, dayOfYear;
+    int32_t eyear, month, dayOfMonth, dayOfYear, unusedRemainder;
 
 
     if(U_FAILURE(status)) { 
@@ -386,10 +386,10 @@ void GregorianCalendar::handleComputeFields(int32_t julianDay, UErrorCode& statu
         // The Julian epoch day (not the same as Julian Day)
         // is zero on Saturday December 30, 0 (Gregorian).
         int32_t julianEpochDay = julianDay - (kJan1_1JulianDay - 2);
-        eyear = (int32_t) Math::floorDivide(4*julianEpochDay + 1464, 1461);
+               eyear = (int32_t) ClockMath::floorDivide((4.0*julianEpochDay) + 1464.0, (int32_t) 1461, unusedRemainder);
 
         // Compute the Julian calendar day number for January 1, eyear
-        int32_t january1 = 365*(eyear-1) + Math::floorDivide(eyear-1, (int32_t)4);
+        int32_t january1 = 365*(eyear-1) + ClockMath::floorDivide(eyear-1, (int32_t)4);
         dayOfYear = (julianEpochDay - january1); // 0-based
 
         // Julian leap years occurred historically every 4 years starting
@@ -535,12 +535,12 @@ int32_t GregorianCalendar::handleComputeMonthStart(int32_t eyear, int32_t month,
     // If the month is out of range, adjust it into range, and
     // modify the extended year value accordingly.
     if (month < 0 || month > 11) {
-        eyear += Math::floorDivide(month, 12, month);
+        eyear += ClockMath::floorDivide(month, 12, month);
     }
 
     UBool isLeap = eyear%4 == 0;
     int32_t y = eyear-1;
-    int32_t julianDay = 365*y + Math::floorDivide(y, 4) + (kJan1_1JulianDay - 3);
+    int32_t julianDay = 365*y + ClockMath::floorDivide(y, 4) + (kJan1_1JulianDay - 3);
 
     nonConstThis->fIsGregorian = (eyear >= fGregorianCutoverYear);
 #if defined (U_DEBUG_CAL)
@@ -578,7 +578,7 @@ int32_t GregorianCalendar::handleGetMonthLength(int32_t extendedYear, int32_t mo
     // If the month is out of range, adjust it into range, and
     // modify the extended year value accordingly.
     if (month < 0 || month > 11) {
-        extendedYear += Math::floorDivide(month, 12, month);
+        extendedYear += ClockMath::floorDivide(month, 12, month);
     }
 
     return isLeapYear(extendedYear) ? kLeapMonthLength[month] : kMonthLength[month];
@@ -697,7 +697,7 @@ GregorianCalendar::getEpochDay(UErrorCode& status)
     // dealing with UDate(Long.MIN_VALUE) and UDate(Long.MAX_VALUE).
     double wallSec = internalGetTime()/1000 + (internalGet(UCAL_ZONE_OFFSET) + internalGet(UCAL_DST_OFFSET))/1000;
 
-    return Math::floorDivide(wallSec, kOneDay/1000.0);
+    return ClockMath::floorDivide(wallSec, kOneDay/1000.0);
 }
 
 // -------------------------------------
@@ -716,7 +716,7 @@ double GregorianCalendar::computeJulianDayOfYear(UBool isGregorian,
 {
     isLeap = year%4 == 0;
     int32_t y = year - 1;
-    double julianDay = 365.0*y + Math::floorDivide(y, 4) + (kJan1_1JulianDay - 3);
+    double julianDay = 365.0*y + ClockMath::floorDivide(y, 4) + (kJan1_1JulianDay - 3);
 
     if (isGregorian) {
         isLeap = isLeap && ((year%100 != 0) || (year%400 == 0));
@@ -785,7 +785,7 @@ double GregorianCalendar::computeJulianDayOfYear(UBool isGregorian,
 double 
 GregorianCalendar::millisToJulianDay(UDate millis)
 {
-    return (double)kEpochStartAsJulianDay + Math::floorDivide(millis, (double)kOneDay);
+    return (double)kEpochStartAsJulianDay + ClockMath::floorDivide(millis, (double)kOneDay);
 }
 
 // -------------------------------------
@@ -850,6 +850,7 @@ GregorianCalendar::roll(UCalendarDateFields field, int32_t amount, UErrorCode& s
                         inCutoverMonth = TRUE;
                     }
             }
+            break;
         default:
             ;
         }
@@ -1174,8 +1175,21 @@ int32_t GregorianCalendar::getActualMaximum(UCalendarDateFields field, UErrorCod
 
 
 int32_t GregorianCalendar::handleGetExtendedYear() {
+    // the year to return
     int32_t year = kEpochYear;
-    switch(resolveFields(kYearPrecedence)) {
+
+    // year field to use
+    int32_t yearField = UCAL_EXTENDED_YEAR;
+
+    // There are three separate fields which could be used to
+    // derive the proper year.  Use the one most recently set.
+    if (fStamp[yearField] < fStamp[UCAL_YEAR])
+        yearField = UCAL_YEAR;
+    if (fStamp[yearField] < fStamp[UCAL_YEAR_WOY])
+        yearField = UCAL_YEAR_WOY;
+
+    // based on the "best" year field, get the year
+    switch(yearField) {
     case UCAL_EXTENDED_YEAR:
         year = internalGet(UCAL_EXTENDED_YEAR, kEpochYear);
         break;
@@ -1251,11 +1265,14 @@ GregorianCalendar::getType() const {
     return "gregorian";
 }
 
-const UDate     GregorianCalendar::fgSystemDefaultCentury        = DBL_MIN;
-const int32_t   GregorianCalendar::fgSystemDefaultCenturyYear    = -1;
-
-UDate           GregorianCalendar::fgSystemDefaultCenturyStart       = DBL_MIN;
-int32_t         GregorianCalendar::fgSystemDefaultCenturyStartYear   = -1;
+/**
+ * The system maintains a static default century start date and Year.  They are
+ * initialized the first time they are used.  Once the system default century date 
+ * and year are set, they do not change.
+ */
+static UDate           gSystemDefaultCenturyStart       = DBL_MIN;
+static int32_t         gSystemDefaultCenturyStartYear   = -1;
+static icu::UInitOnce  gSystemDefaultCenturyInit        = U_INITONCE_INITIALIZER;
 
 
 UBool GregorianCalendar::haveDefaultCentury() const
@@ -1263,82 +1280,37 @@ UBool GregorianCalendar::haveDefaultCentury() const
     return TRUE;
 }
 
-UDate GregorianCalendar::defaultCenturyStart() const
+static void U_CALLCONV
+initializeSystemDefaultCentury()
 {
-    return internalGetDefaultCenturyStart();
-}
-
-int32_t GregorianCalendar::defaultCenturyStartYear() const
-{
-    return internalGetDefaultCenturyStartYear();
+    // initialize systemDefaultCentury and systemDefaultCenturyYear based
+    // on the current time.  They'll be set to 80 years before
+    // the current time.
+    UErrorCode status = U_ZERO_ERROR;
+    GregorianCalendar calendar(status);
+    if (U_SUCCESS(status)) {
+        calendar.setTime(Calendar::getNow(), status);
+        calendar.add(UCAL_YEAR, -80, status);
+
+        gSystemDefaultCenturyStart = calendar.getTime(status);
+        gSystemDefaultCenturyStartYear = calendar.get(UCAL_YEAR, status);
+    }
+    // We have no recourse upon failure unless we want to propagate the failure
+    // out.
 }
 
-UDate
-GregorianCalendar::internalGetDefaultCenturyStart() const
-{
+UDate GregorianCalendar::defaultCenturyStart() const {
     // lazy-evaluate systemDefaultCenturyStart
-    UBool needsUpdate;
-    UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
-
-    if (needsUpdate) {
-        initializeSystemDefaultCentury();
-    }
-
-    // use defaultCenturyStart unless it's the flag value;
-    // then use systemDefaultCenturyStart
-
-    return fgSystemDefaultCenturyStart;
+    umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
+    return gSystemDefaultCenturyStart;
 }
 
-int32_t
-GregorianCalendar::internalGetDefaultCenturyStartYear() const
-{
+int32_t GregorianCalendar::defaultCenturyStartYear() const {
     // lazy-evaluate systemDefaultCenturyStartYear
-    UBool needsUpdate;
-    UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
-
-    if (needsUpdate) {
-        initializeSystemDefaultCentury();
-    }
-
-    // use defaultCenturyStart unless it's the flag value;
-    // then use systemDefaultCenturyStartYear
-
-    return fgSystemDefaultCenturyStartYear;
+    umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
+    return gSystemDefaultCenturyStartYear;
 }
 
-void
-GregorianCalendar::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;
-        Calendar *calendar = new GregorianCalendar(status);
-        if (calendar != NULL && 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);
-                fgSystemDefaultCenturyStart = newStart;
-                fgSystemDefaultCenturyStartYear = newYear;
-                umtx_unlock(NULL);
-            }
-            delete calendar;
-        }
-        // We have no recourse upon failure unless we want to propagate the failure
-        // out.
-    }
-}
-
-
 U_NAMESPACE_END
 
 #endif /* #if !UCONFIG_NO_FORMATTING */