]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/i18n/islamcal.cpp
ICU-461.13.tar.gz
[apple/icu.git] / icuSources / i18n / islamcal.cpp
index eda1cc3642e2081ecf0dbd5a89cf60ad4147b30f..5ae94af082aa79a9aa5bdeaaef5185a6a2635944 100644 (file)
@@ -1,22 +1,23 @@
 /*
- * Copyright (C) 2003-2004, International Business Machines Corporation
- * and others. All Rights Reserved.
- ******************************************************************************
- *
- * File ISLAMCAL.H
- *
- * Modification History:
- *
- *   Date        Name        Description
- *   10/14/2003  srl         ported from java IslamicCalendar
- *****************************************************************************
- */
+******************************************************************************
+* Copyright (C) 2003-2010, International Business Machines Corporation
+* and others. All Rights Reserved.
+******************************************************************************
+*
+* File ISLAMCAL.H
+*
+* Modification History:
+*
+*   Date        Name        Description
+*   10/14/2003  srl         ported from java IslamicCalendar
+*****************************************************************************
+*/
 
 #include "islamcal.h"
 
 #if !UCONFIG_NO_FORMATTING
 
-#include "mutex.h"
+#include "umutex.h"
 #include <float.h>
 #include "gregoimp.h" // Math
 #include "astro.h" // CalendarAstronomer
@@ -31,15 +32,15 @@ static const UDate HIJRA_MILLIS = -42521587200000.0;    // 7/16/622 AD 00:00
 # include <stdarg.h>
 static void debug_islamcal_loc(const char *f, int32_t l)
 {
-  fprintf(stderr, "%s:%d: ", f, l);
+    fprintf(stderr, "%s:%d: ", f, l);
 }
 
 static void debug_islamcal_msg(const char *pat, ...)
 {
-  va_list ap;
-  va_start(ap, pat);
-  vfprintf(stderr, pat, ap);
-  fflush(stderr);
+    va_list ap;
+    va_start(ap, pat);
+    vfprintf(stderr, pat, ap);
+    fflush(stderr);
 }
 // must use double parens, i.e.:  U_DEBUG_ISLAMCAL_MSG(("four is: %d",4));
 #define U_DEBUG_ISLAMCAL_MSG(x) {debug_islamcal_loc(__FILE__,__LINE__);debug_islamcal_msg x;}
@@ -51,8 +52,8 @@ static void debug_islamcal_msg(const char *pat, ...)
 // --- The cache --
 // cache of months
 static UMTX astroLock = 0;  // pod bay door lock
-static CalendarCache *gMonthCache = NULL;
-static CalendarAstronomer *gIslamicCalendarAstro = NULL;
+static U_NAMESPACE_QUALIFIER CalendarCache *gMonthCache = NULL;
+static U_NAMESPACE_QUALIFIER CalendarAstronomer *gIslamicCalendarAstro = NULL;
 
 U_CDECL_BEGIN
 static UBool calendar_islamic_cleanup(void) {
@@ -78,22 +79,22 @@ U_NAMESPACE_BEGIN
 //-------------------------------------------------------------------------
 
 const char *IslamicCalendar::getType() const { 
-  if(civil==CIVIL) {
-    return "islamic-civil";
-  } else {
-    return "islamic";
-  }
+    if(civil==CIVIL) {
+        return "islamic-civil";
+    } else {
+        return "islamic";
+    }
 }
 
 Calendar* IslamicCalendar::clone() const {
-  return new IslamicCalendar(*this);
+    return new IslamicCalendar(*this);
 }
 
 IslamicCalendar::IslamicCalendar(const Locale& aLocale, UErrorCode& success, ECivil beCivil)
-  :   Calendar(TimeZone::createDefault(), aLocale, success),
-      civil(beCivil)
+:   Calendar(TimeZone::createDefault(), aLocale, success),
+civil(beCivil)
 {
-  setTimeInMillis(getNow(), success); // Call this again now that the vtable is set up properly.
+    setTimeInMillis(getNow(), success); // Call this again now that the vtable is set up properly.
 }
 
 IslamicCalendar::IslamicCalendar(const IslamicCalendar& other) : Calendar(other), civil(other.civil) {
@@ -104,71 +105,75 @@ IslamicCalendar::~IslamicCalendar()
 }
 
 /**
- * Determines whether this object uses the fixed-cycle Islamic civil calendar
- * or an approximation of the religious, astronomical calendar.
- *
- * @param beCivil   <code>true</code> to use the civil calendar,
- *                  <code>false</code> to use the astronomical calendar.
- * @draft ICU 2.4
- */
+* Determines whether this object uses the fixed-cycle Islamic civil calendar
+* or an approximation of the religious, astronomical calendar.
+*
+* @param beCivil   <code>true</code> to use the civil calendar,
+*                  <code>false</code> to use the astronomical calendar.
+* @draft ICU 2.4
+*/
 void IslamicCalendar::setCivil(ECivil beCivil, UErrorCode &status)
 {
-  if (civil != beCivil) {
-    // The fields of the calendar will become invalid, because the calendar
-    // rules are different
-    UDate m = getTimeInMillis(status);
-    civil = beCivil;
-    clear();
-    setTimeInMillis(m, status);
-  }
+    if (civil != beCivil) {
+        // The fields of the calendar will become invalid, because the calendar
+        // rules are different
+        UDate m = getTimeInMillis(status);
+        civil = beCivil;
+        clear();
+        setTimeInMillis(m, status);
+    }
 }
-    
+
 /**
- * Returns <code>true</code> if this object is using the fixed-cycle civil
- * calendar, or <code>false</code> if using the religious, astronomical
- * calendar.
- * @draft ICU 2.4
- */
+* Returns <code>true</code> if this object is using the fixed-cycle civil
+* calendar, or <code>false</code> if using the religious, astronomical
+* calendar.
+* @draft ICU 2.4
+*/
 UBool IslamicCalendar::isCivil() {
-  return (civil == CIVIL);
+    return (civil == CIVIL);
 }
-    
+
 //-------------------------------------------------------------------------
 // Minimum / Maximum access functions
 //-------------------------------------------------------------------------
 
+// Note: Current IslamicCalendar implementation does not work
+// well with negative years.
+
 static const int32_t LIMITS[UCAL_FIELD_COUNT][4] = {
-  // Minimum  Greatest    Least  Maximum
-  //           Minimum  Maximum
-  {        0,        0,       0,       0 }, // ERA
-  {        1,        1, 5000000, 5000000 }, // YEAR
-  {        0,        0,      11,      11 }, // MONTH
-  {        1,        1,      51,      52 }, // WEEK_OF_YEAR
-  {        0,        0,       5,       6 }, // WEEK_OF_MONTH
-  {        1,        1,      29,      30 }, // DAY_OF_MONTH
-  {        1,        1,     354,     355 }, // DAY_OF_YEAR
-  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // DAY_OF_WEEK
-  {       -1,       -1,       4,       5 }, // DAY_OF_WEEK_IN_MONTH
-  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // AM_PM
-  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // HOUR
-  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // HOUR_OF_DAY
-  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // MINUTE
-  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // SECOND
-  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // MILLISECOND
-  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // ZONE_OFFSET
-  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // DST_OFFSET
-  { 1, 1, 5000001, 5000001 }, // YEAR_WOY
-  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // DOW_LOCAL
-  { 1, 1, 5000000, 5000000 }, // EXTENDED_YEAR
-  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // JULIAN_DAY
-  {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1} // MILLISECONDS_IN_DAY
+    // Minimum  Greatest    Least  Maximum
+    //           Minimum  Maximum
+    {        0,        0,        0,        0}, // ERA
+    {        1,        1,  5000000,  5000000}, // YEAR
+    {        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,      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
+    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // AM_PM
+    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // HOUR
+    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // HOUR_OF_DAY
+    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // MINUTE
+    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // SECOND
+    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // MILLISECOND
+    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // ZONE_OFFSET
+    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // DST_OFFSET
+    {        1,        1,  5000000,  5000000}, // YEAR_WOY
+    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // DOW_LOCAL
+    {        1,        1,  5000000,  5000000}, // EXTENDED_YEAR
+    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // JULIAN_DAY
+    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // MILLISECONDS_IN_DAY
+    {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // IS_LEAP_MONTH
 };
 
 /**
- * @draft ICU 2.4
- */
+* @draft ICU 2.4
+*/
 int32_t IslamicCalendar::handleGetLimit(UCalendarDateFields field, ELimitType limitType) const {
-  return LIMITS[field][limitType];
+    return LIMITS[field][limitType];
 }
 
 //-------------------------------------------------------------------------
@@ -176,113 +181,128 @@ int32_t IslamicCalendar::handleGetLimit(UCalendarDateFields field, ELimitType li
 //
 
 /**
- * Determine whether a year is a leap year in the Islamic civil calendar
- */
+* Determine whether a year is a leap year in the Islamic civil calendar
+*/
 UBool IslamicCalendar::civilLeapYear(int32_t year)
 {
-  return (14 + 11 * year) % 30 < 11;
+    return (14 + 11 * year) % 30 < 11;
 }
-    
+
 /**
- * Return the day # on which the given year starts.  Days are counted
- * from the Hijri epoch, origin 0.
- */
+* Return the day # on which the given year starts.  Days are counted
+* from the Hijri epoch, origin 0.
+*/
 int32_t IslamicCalendar::yearStart(int32_t year) {
-  if (civil == CIVIL) {
-    return (year-1)*354 + Math::floorDivide((3+11*year),30);
-  } else {
-    return trueMonthStart(12*(year-1));
-  }
+    if (civil == CIVIL) {
+        return (year-1)*354 + ClockMath::floorDivide((3+11*year),30);
+    } else {
+        return trueMonthStart(12*(year-1));
+    }
 }
-    
+
 /**
- * Return the day # on which the given month starts.  Days are counted
- * from the Hijri epoch, origin 0.
- *
- * @param year  The hijri year
- * @param year  The hijri month, 0-based
- */
+* Return the day # on which the given month starts.  Days are counted
+* from the Hijri epoch, origin 0.
+*
+* @param year  The hijri year
+* @param year  The hijri month, 0-based
+*/
 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);
-  } else {
-    return trueMonthStart(12*(year-1) + month);
-  }
+    if (civil == CIVIL) {
+        return (int32_t)uprv_ceil(29.5*month)
+            + (year-1)*354 + (int32_t)ClockMath::floorDivide((3+11*year),30);
+    } else {
+        return trueMonthStart(12*(year-1) + month);
+    }
 }
-    
+
 /**
- * Find the day number on which a particular month of the true/lunar
- * Islamic calendar starts.
- *
- * @param month The month in question, origin 0 from the Hijri epoch
- *
- * @return The day number on which the given month starts.
- */
+* Find the day number on which a particular month of the true/lunar
+* Islamic calendar starts.
+*
+* @param month The month in question, origin 0 from the Hijri epoch
+*
+* @return The day number on which the given month starts.
+*/
 int32_t IslamicCalendar::trueMonthStart(int32_t month) const
 {
-  UErrorCode status = U_ZERO_ERROR;
-  int32_t start = CalendarCache::get(&gMonthCache, month, status);
-  
-  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;
-    
-    double age = moonAge(origin);
-    
-    if (moonAge(origin) >= 0) {
-      // The month has already started
-      do {
-        origin -= kOneDay;
-        age = moonAge(origin);
-      } while (age >= 0);
+    UErrorCode status = U_ZERO_ERROR;
+    int32_t start = CalendarCache::get(&gMonthCache, month, status);
+
+    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) * kOneDay;
+
+        // moonAge will fail due to memory allocation error
+        double age = moonAge(origin, status);
+        if (U_FAILURE(status)) {
+            goto trueMonthStartEnd;
+        }
+
+        if (age >= 0) {
+            // The month has already started
+            do {
+                origin -= kOneDay;
+                age = moonAge(origin, status);
+                if (U_FAILURE(status)) {
+                    goto trueMonthStartEnd;
+                }
+            } while (age >= 0);
+        }
+        else {
+            // Preceding month has not ended yet.
+            do {
+                origin += kOneDay;
+                age = moonAge(origin, status);
+                if (U_FAILURE(status)) {
+                    goto trueMonthStartEnd;
+                }
+            } while (age < 0);
+        }
+        start = (int32_t)ClockMath::floorDivide((origin - HIJRA_MILLIS), (double)kOneDay) + 1;
+        CalendarCache::put(&gMonthCache, month, start, status);
     }
-    else {
-      // Preceding month has not ended yet.
-      do {
-          origin += kOneDay;
-        age = moonAge(origin);
-      } while (age < 0);
+trueMonthStartEnd :
+    if(U_FAILURE(status)) {
+        start = 0;
     }
-    start = (int32_t)Math::floorDivide((origin - HIJRA_MILLIS), (double)kOneDay) + 1;
-    CalendarCache::put(&gMonthCache, month, start, status);
-  }
-  if(U_FAILURE(status)) {
-    start = 0;
-  }
-  return start;
+    return start;
 }
 
 /**
- * Return the "age" of the moon at the given time; this is the difference
- * in ecliptic latitude between the moon and the sun.  This method simply
- * calls CalendarAstronomer.moonAge, converts to degrees, 
- * and adjusts the result to be in the range [-180, 180].
- *
- * @param time  The time at which the moon's age is desired,
- *              in millis since 1/1/1970.
- */
-double IslamicCalendar::moonAge(UDate time)
+* Return the "age" of the moon at the given time; this is the difference
+* in ecliptic latitude between the moon and the sun.  This method simply
+* calls CalendarAstronomer.moonAge, converts to degrees, 
+* and adjusts the result to be in the range [-180, 180].
+*
+* @param time  The time at which the moon's age is desired,
+*              in millis since 1/1/1970.
+*/
+double IslamicCalendar::moonAge(UDate time, UErrorCode &status)
 {
-  double age = 0;
-
-  umtx_lock(&astroLock);
-  if(gIslamicCalendarAstro == NULL) {
-    gIslamicCalendarAstro = new CalendarAstronomer();
-  }
-  gIslamicCalendarAstro->setTime(time);
-  age = gIslamicCalendarAstro->getMoonAge();
-  ucln_i18n_registerCleanup(UCLN_I18N_ISLAMIC_CALENDAR, calendar_islamic_cleanup);
-  umtx_unlock(&astroLock);
-
-  // Convert to degrees and normalize...
-  age = age * 180 / CalendarAstronomer::PI;
-  if (age > 180) {
-    age = age - 360;
-  }
-
-  return age;
+    double age = 0;
+
+    umtx_lock(&astroLock);
+    if(gIslamicCalendarAstro == NULL) {
+        gIslamicCalendarAstro = new CalendarAstronomer();
+        if (gIslamicCalendarAstro == NULL) {
+            status = U_MEMORY_ALLOCATION_ERROR;
+            return age;
+        }
+        ucln_i18n_registerCleanup(UCLN_I18N_ISLAMIC_CALENDAR, calendar_islamic_cleanup);
+    }
+    gIslamicCalendarAstro->setTime(time);
+    age = gIslamicCalendarAstro->getMoonAge();
+    umtx_unlock(&astroLock);
+
+    // Convert to degrees and normalize...
+    age = age * 180 / CalendarAstronomer::PI;
+    if (age > 180) {
+        age = age - 360;
+    }
+
+    return age;
 }
 
 //----------------------------------------------------------------------
@@ -290,60 +310,60 @@ double IslamicCalendar::moonAge(UDate time)
 //----------------------------------------------------------------------
 
 /**
- * Return the length (in days) of the given month.
- *
- * @param year  The hijri year
- * @param year  The hijri month, 0-based
- * @draft ICU 2.4
- */
+* Return the length (in days) of the given month.
+*
+* @param year  The hijri year
+* @param year  The hijri month, 0-based
+* @draft ICU 2.4
+*/
 int32_t IslamicCalendar::handleGetMonthLength(int32_t extendedYear, int32_t month) const {
 
-  int32_t length = 0;
-        
-  if (civil == CIVIL) {
-    length = 29 + (month+1) % 2;
-    if (month == DHU_AL_HIJJAH && civilLeapYear(extendedYear)) {
-      length++;
+    int32_t length = 0;
+
+    if (civil == CIVIL) {
+        length = 29 + (month+1) % 2;
+        if (month == DHU_AL_HIJJAH && civilLeapYear(extendedYear)) {
+            length++;
+        }
+    } else {
+        month = 12*(extendedYear-1) + month;
+        length =  trueMonthStart(month+1) - trueMonthStart(month) ;
     }
-  } else {
-    month = 12*(extendedYear-1) + month;
-    length =  trueMonthStart(month+1) - trueMonthStart(month) ;
-  }
-  return length;
+    return length;
 }
 
 /**
- * Return the number of days in the given Islamic year
- * @draft ICU 2.4
- */
+* Return the number of days in the given Islamic year
+* @draft ICU 2.4
+*/
 int32_t IslamicCalendar::handleGetYearLength(int32_t extendedYear) const {
-  if (civil == CIVIL) {
-    return 354 + (civilLeapYear(extendedYear) ? 1 : 0);
-  } else {
-    int32_t month = 12*(extendedYear-1);
-    return (trueMonthStart(month + 12) - trueMonthStart(month));
-  }
+    if (civil == CIVIL) {
+        return 354 + (civilLeapYear(extendedYear) ? 1 : 0);
+    } else {
+        int32_t month = 12*(extendedYear-1);
+        return (trueMonthStart(month + 12) - trueMonthStart(month));
+    }
 }
-    
+
 //-------------------------------------------------------------------------
 // Functions for converting from field values to milliseconds....
 //-------------------------------------------------------------------------
 
 // Return JD of start of given month/year
 /**
- * @draft ICU 2.4
- */
+* @draft ICU 2.4
+*/
 int32_t IslamicCalendar::handleComputeMonthStart(int32_t eyear, int32_t month, UBool /* useMonth */) const {
-  return monthStart(eyear, month) + 1948439;
+    return monthStart(eyear, month) + 1948439;
 }    
 
 //-------------------------------------------------------------------------
 // Functions for converting from milliseconds to field values
 //-------------------------------------------------------------------------
 
-    /**
-     * @draft ICU 2.4
-     */
+/**
+* @draft ICU 2.4
+*/
 int32_t IslamicCalendar::handleGetExtendedYear() {
     int32_t year;
     if (newerField(UCAL_EXTENDED_YEAR, UCAL_YEAR) == UCAL_EXTENDED_YEAR) {
@@ -355,29 +375,29 @@ int32_t IslamicCalendar::handleGetExtendedYear() {
 }
 
 /**
- * Override Calendar to compute several fields specific to the Islamic
- * calendar system.  These are:
- *
- * <ul><li>ERA
- * <li>YEAR
- * <li>MONTH
- * <li>DAY_OF_MONTH
- * <li>DAY_OF_YEAR
- * <li>EXTENDED_YEAR</ul>
- 
- * The DAY_OF_WEEK and DOW_LOCAL fields are already set when this
- * method is called. The getGregorianXxx() methods return Gregorian
- * calendar equivalents for the given Julian day.
-     * @draft ICU 2.4
-     */
-void IslamicCalendar::handleComputeFields(int32_t julianDay, UErrorCode &/*status*/) {
+* Override Calendar to compute several fields specific to the Islamic
+* calendar system.  These are:
+*
+* <ul><li>ERA
+* <li>YEAR
+* <li>MONTH
+* <li>DAY_OF_MONTH
+* <li>DAY_OF_YEAR
+* <li>EXTENDED_YEAR</ul>
+* 
+* The DAY_OF_WEEK and DOW_LOCAL fields are already set when this
+* method is called. The getGregorianXxx() methods return Gregorian
+* calendar equivalents for the given Julian day.
+* @draft ICU 2.4
+*/
+void IslamicCalendar::handleComputeFields(int32_t julianDay, UErrorCode &status) {
     int32_t year, month, dayOfMonth, dayOfYear;
     UDate startDate;
     int32_t days = julianDay - 1948440;
-    
+
     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);
@@ -385,9 +405,14 @@ void IslamicCalendar::handleComputeFields(int32_t julianDay, UErrorCode &/*statu
         // 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);
 
-        if ( days - startDate >= 28 && moonAge(internalGetTime()) > 0) {
+        double age = moonAge(internalGetTime(), status);
+        if (U_FAILURE(status)) {
+               status = U_MEMORY_ALLOCATION_ERROR;
+               return;
+        }
+        if ( days - startDate >= 25 && age > 0) {
             // If we're near the end of the month, assume next month and search backwards
             months++;
         }
@@ -398,11 +423,11 @@ void IslamicCalendar::handleComputeFields(int32_t julianDay, UErrorCode &/*statu
             // If it was after the date in question, back up a month and try again
             months--;
         }
-        
+
         year = months / 12 + 1;
         month = months % 12;
     }
-    
+
     dayOfMonth = (days - monthStart(year, month)) + 1;
 
     // Now figure out the day of the year.
@@ -419,14 +444,14 @@ void IslamicCalendar::handleComputeFields(int32_t julianDay, UErrorCode &/*statu
 UBool
 IslamicCalendar::inDaylightTime(UErrorCode& status) const
 {
-// copied from GregorianCalendar
-if (U_FAILURE(status) || !getTimeZone().useDaylightTime()) 
-  return FALSE;
+    // copied from GregorianCalendar
+    if (U_FAILURE(status) || (&(getTimeZone()) == NULL && !getTimeZone().useDaylightTime())) 
+        return FALSE;
 
     // Force an update of the state of the Calendar.
-((IslamicCalendar*)this)->complete(status); // cast away const
+    ((IslamicCalendar*)this)->complete(status); // cast away const
 
-return (UBool)(U_SUCCESS(status) ? (internalGet(UCAL_DST_OFFSET) != 0) : FALSE);
+    return (UBool)(U_SUCCESS(status) ? (internalGet(UCAL_DST_OFFSET) != 0) : FALSE);
 }
 
 // default century
@@ -439,85 +464,77 @@ int32_t         IslamicCalendar::fgSystemDefaultCenturyStartYear   = -1;
 
 UBool IslamicCalendar::haveDefaultCentury() const
 {
-  return TRUE;
+    return TRUE;
 }
 
 UDate IslamicCalendar::defaultCenturyStart() const
 {
-  return internalGetDefaultCenturyStart();
+    return internalGetDefaultCenturyStart();
 }
 
 int32_t IslamicCalendar::defaultCenturyStartYear() const
 {
-  return internalGetDefaultCenturyStartYear();
+    return internalGetDefaultCenturyStartYear();
 }
 
 UDate
 IslamicCalendar::internalGetDefaultCenturyStart() const
 {
-  // lazy-evaluate systemDefaultCenturyStart
-  UBool needsUpdate;
-  { 
-    Mutex m;
-    needsUpdate = (fgSystemDefaultCenturyStart == fgSystemDefaultCentury);
-  }
-
-  if (needsUpdate) {
-    initializeSystemDefaultCentury();
-  }
-
-  // use defaultCenturyStart unless it's the flag value;
-  // then use systemDefaultCenturyStart
-  
-  return fgSystemDefaultCenturyStart;
+    // 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;
 }
 
 int32_t
 IslamicCalendar::internalGetDefaultCenturyStartYear() const
 {
-  // lazy-evaluate systemDefaultCenturyStartYear
-  UBool needsUpdate;
-  { 
-    Mutex m;
-    needsUpdate = (fgSystemDefaultCenturyStart == fgSystemDefaultCentury);
-  }
-
-  if (needsUpdate) {
-    initializeSystemDefaultCentury();
-  }
-
-  // use defaultCenturyStart unless it's the flag value;
-  // then use systemDefaultCenturyStartYear
-  
-  return    fgSystemDefaultCenturyStartYear;
+    // 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;
 }
 
 void
 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)
-  {
+    // 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;
     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);
-      {
-        Mutex m;
-        fgSystemDefaultCenturyStart = newStart;
-        fgSystemDefaultCenturyStartYear = newYear;
-      }
+        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)
+        {
+            fgSystemDefaultCenturyStartYear = newYear;
+            fgSystemDefaultCenturyStart = newStart;
+        }
+        umtx_unlock(NULL);
     }
     // We have no recourse upon failure unless we want to propagate the failure
     // out.
-  }
 }
 
 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IslamicCalendar)