]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/i18n/calendar.cpp
ICU-62141.0.1.tar.gz
[apple/icu.git] / icuSources / i18n / calendar.cpp
index 49162a6c15354b826343fb235d605bcc0aa649a4..26e9465eaf1e64247fd57d052907e2e5414f5367 100644 (file)
@@ -1,17 +1,19 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
 /*
 *******************************************************************************
-* Copyright (C) 1997-2015, International Business Machines Corporation and    *
+* Copyright (C) 1997-2016, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 *
 * File CALENDAR.CPP
 *
-* Modification History: 
+* Modification History:
 *
 *   Date        Name        Description
 *   02/03/97    clhuang     Creation.
-*   04/22/97    aliu        Cleaned up, fixed memory leak, made 
-*                           setWeekCountData() more robust.  
+*   04/22/97    aliu        Cleaned up, fixed memory leak, made
+*                           setWeekCountData() more robust.
 *                           Moved platform code to TPlatformUtilities.
 *   05/01/97    aliu        Made equals(), before(), after() arguments const.
 *   05/20/97    aliu        Changed logic of when to compute fields and time
@@ -24,7 +26,7 @@
 *******************************************************************************
 */
 
-#include "utypeinfo.h"  // for 'typeid' to work 
+#include "utypeinfo.h"  // for 'typeid' to work
 
 #include "unicode/utypes.h"
 
 #include "olsontz.h"
 #include "sharedcalendar.h"
 #include "unifiedcache.h"
+#include "ulocimp.h"
 
 #if !UCONFIG_NO_SERVICE
 static icu::ICULocaleService* gService = NULL;
 static icu::UInitOnce gServiceInitOnce = U_INITONCE_INITIALIZER;
-#endif
 
 // INTERNAL - for cleanup
-
 U_CDECL_BEGIN
 static UBool calendar_cleanup(void) {
 #if !UCONFIG_NO_SERVICE
@@ -79,6 +80,7 @@ static UBool calendar_cleanup(void) {
     return TRUE;
 }
 U_CDECL_END
+#endif
 
 // ------------------------------------------
 //
@@ -90,9 +92,9 @@ U_CDECL_END
 
 #if defined( U_DEBUG_CALSVC ) || defined (U_DEBUG_CAL)
 
-/** 
- * fldName was removed as a duplicate implementation. 
- * use  udbg_ services instead, 
+/**
+ * fldName was removed as a duplicate implementation.
+ * use  udbg_ services instead,
  * which depend on include files and library from ../tools/toolutil, the following circular link:
  *   CPPFLAGS+=-I$(top_srcdir)/tools/toolutil
  *   LIBS+=$(LIBICUTOOLUTIL)
@@ -120,7 +122,7 @@ void ucal_dump(const Calendar &cal) {
 void Calendar::dump() const {
     int i;
     fprintf(stderr, "@calendar=%s, timeset=%c, fieldset=%c, allfields=%c, virtualset=%c, t=%.2f",
-        getType(), fIsTimeSet?'y':'n',  fAreFieldsSet?'y':'n',  fAreAllFieldsSet?'y':'n',  
+        getType(), fIsTimeSet?'y':'n',  fAreFieldsSet?'y':'n',  fAreAllFieldsSet?'y':'n',
         fAreFieldsVirtuallySet?'y':'n',
         fTime);
 
@@ -132,9 +134,9 @@ void Calendar::dump() const {
         fprintf(stderr, "  %25s: %-11ld", f, fFields[i]);
         if(fStamp[i] == kUnset) {
             fprintf(stderr, " (unset) ");
-        } else if(fStamp[i] == kInternallySet) { 
+        } else if(fStamp[i] == kInternallySet) {
             fprintf(stderr, " (internally set) ");
-            //} else if(fStamp[i] == kInternalDefault) { 
+            //} else if(fStamp[i] == kInternalDefault) {
             //    fprintf(stderr, " (internal default) ");
         } else {
             fprintf(stderr, " %%%d ", fStamp[i]);
@@ -210,7 +212,7 @@ const SharedCalendar *LocaleCacheKey<SharedCalendar>::createObject(
         const void * /*unusedCreationContext*/, UErrorCode &status) const {
     Calendar *calendar = Calendar::makeInstance(fLoc, status);
     if (U_FAILURE(status)) {
-        return NULL; 
+        return NULL;
     }
     SharedCalendar *shared = new SharedCalendar(calendar);
     if (shared == NULL) {
@@ -231,7 +233,9 @@ static ECalType getCalendarType(const char *s) {
     return CALTYPE_UNKNOWN;
 }
 
-static UBool isStandardSupportedKeyword(const char *keyword, UErrorCode& status) { 
+#if !UCONFIG_NO_SERVICE
+// Only used with service registration.
+static UBool isStandardSupportedKeyword(const char *keyword, UErrorCode& status) {
     if(U_FAILURE(status)) {
         return FALSE;
     }
@@ -239,6 +243,7 @@ static UBool isStandardSupportedKeyword(const char *keyword, UErrorCode& status)
     return (calType != CALTYPE_UNKNOWN);
 }
 
+// only used with service registration.
 static void getCalendarKeyword(const UnicodeString &id, char *targetBuffer, int32_t targetBufferSize) {
     UnicodeString calendarKeyword = UNICODE_STRING_SIMPLE("calendar=");
     int32_t calKeyLen = calendarKeyword.length();
@@ -252,6 +257,7 @@ static void getCalendarKeyword(const UnicodeString &id, char *targetBuffer, int3
     }
     targetBuffer[keyLen] = 0;
 }
+#endif
 
 static ECalType getCalendarTypeForLocale(const char *locid) {
     UErrorCode status = U_ZERO_ERROR;
@@ -284,18 +290,11 @@ static ECalType getCalendarTypeForLocale(const char *locid) {
     // when calendar keyword is not available or not supported, read supplementalData
     // to get the default calendar type for the locale's region
     char region[ULOC_COUNTRY_CAPACITY];
-    int32_t regionLen = 0;
-    regionLen = uloc_getCountry(canonicalName, region, sizeof(region) - 1, &status);
-    if (regionLen == 0) {
-        char fullLoc[256];
-        uloc_addLikelySubtags(locid, fullLoc, sizeof(fullLoc) - 1, &status);
-        regionLen = uloc_getCountry(fullLoc, region, sizeof(region) - 1, &status);
-    }
+    (void)ulocimp_getRegionForSupplementalData(canonicalName, TRUE, region, sizeof(region), &status);
     if (U_FAILURE(status)) {
         return CALTYPE_GREGORIAN;
     }
-    region[regionLen] = 0;
-    
+
     // Read preferred calendar values from supplementalData calendarPreference
     UResourceBundle *rb = ures_openDirect(NULL, "supplementalData", &status);
     ures_getByKey(rb, "calendarPreferenceData", rb, &status);
@@ -398,7 +397,7 @@ static Calendar *createStandardCalendar(ECalType calType, const Locale &loc, UEr
 // -------------------------------------
 
 /**
-* a Calendar Factory which creates the "basic" calendar types, that is, those 
+* a Calendar Factory which creates the "basic" calendar types, that is, those
 * shipped with ICU.
 */
 class BasicCalendarFactory : public LocaleKeyFactory {
@@ -412,7 +411,7 @@ public:
     virtual ~BasicCalendarFactory();
 
 protected:
-    //virtual UBool isSupportedID( const UnicodeString& id, UErrorCode& status) const { 
+    //virtual UBool isSupportedID( const UnicodeString& id, UErrorCode& status) const {
     //  if(U_FAILURE(status)) {
     //    return FALSE;
     //  }
@@ -470,7 +469,7 @@ protected:
 
 BasicCalendarFactory::~BasicCalendarFactory() {}
 
-/** 
+/**
 * A factory which looks up the DefaultCalendar resource to determine which class of calendar to use
 */
 
@@ -514,7 +513,7 @@ public:
     virtual UObject* cloneInstance(UObject* instance) const {
         UnicodeString *s = dynamic_cast<UnicodeString *>(instance);
         if(s != NULL) {
-            return s->clone(); 
+            return s->clone();
         } else {
 #ifdef U_DEBUG_CALSVC_F
             UErrorCode status2 = U_ZERO_ERROR;
@@ -577,7 +576,7 @@ initCalendarService(UErrorCode &status)
         fprintf(stderr, "Registering classes..\n");
 #endif
 
-        // Register all basic instances. 
+        // Register all basic instances.
     gService->registerFactory(new BasicCalendarFactory(),status);
 
 #ifdef U_DEBUG_CALSVC
@@ -593,7 +592,7 @@ initCalendarService(UErrorCode &status)
     }
         }
 
-static ICULocaleService* 
+static ICULocaleService*
 getCalendarService(UErrorCode &status)
 {
     umtx_initOnce(gServiceInitOnce, &initCalendarService, status);
@@ -640,7 +639,9 @@ static const int32_t kCalendarLimits[UCAL_FIELD_COUNT][4] = {
 };
 
 // Resource bundle tags read by this class
+static const char gCalendar[] = "calendar";
 static const char gMonthNames[] = "monthNames";
+static const char gGregorian[] = "gregorian";
 
 // Data flow in Calendar
 // ---------------------
@@ -707,6 +708,8 @@ fZone(NULL),
 fRepeatedWallTime(UCAL_WALLTIME_LAST),
 fSkippedWallTime(UCAL_WALLTIME_LAST)
 {
+    validLocale[0] = 0;
+    actualLocale[0] = 0;
     clear();
     if (U_FAILURE(success)) {
         return;
@@ -733,6 +736,8 @@ fZone(NULL),
 fRepeatedWallTime(UCAL_WALLTIME_LAST),
 fSkippedWallTime(UCAL_WALLTIME_LAST)
 {
+    validLocale[0] = 0;
+    actualLocale[0] = 0;
     if (U_FAILURE(success)) {
         return;
     }
@@ -745,7 +750,7 @@ fSkippedWallTime(UCAL_WALLTIME_LAST)
         return;
     }
 
-    clear();    
+    clear();
     fZone = zone;
     setWeekData(aLocale, NULL, success);
 }
@@ -765,6 +770,8 @@ fZone(NULL),
 fRepeatedWallTime(UCAL_WALLTIME_LAST),
 fSkippedWallTime(UCAL_WALLTIME_LAST)
 {
+    validLocale[0] = 0;
+    actualLocale[0] = 0;
     if (U_FAILURE(success)) {
         return;
     }
@@ -821,8 +828,10 @@ Calendar::operator=(const Calendar &right)
         fWeekendCease            = right.fWeekendCease;
         fWeekendCeaseMillis      = right.fWeekendCeaseMillis;
         fNextStamp               = right.fNextStamp;
-        uprv_strcpy(validLocale, right.validLocale);
-        uprv_strcpy(actualLocale, right.actualLocale);
+        uprv_strncpy(validLocale, right.validLocale, sizeof(validLocale));
+        uprv_strncpy(actualLocale, right.actualLocale, sizeof(actualLocale));
+        validLocale[sizeof(validLocale)-1] = 0;
+        actualLocale[sizeof(validLocale)-1] = 0;
     }
 
     return *this;
@@ -852,7 +861,7 @@ Calendar::createInstance(const Locale& aLocale, UErrorCode& success)
     return createInstance(TimeZone::createDefault(), aLocale, success);
 }
 
-// ------------------------------------- Adopting 
+// ------------------------------------- Adopting
 
 // Note: this is the bottleneck that actually calls the service routines.
 
@@ -905,7 +914,7 @@ Calendar::makeInstance(const Locale& aLocale, UErrorCode& success) {
         c = (Calendar*)getCalendarService(success)->get(l, LocaleKey::KIND_ANY, &actualLoc2, success);
 
         if(U_FAILURE(success) || !c) {
-            if(U_SUCCESS(success)) { 
+            if(U_SUCCESS(success)) {
                 success = U_INTERNAL_PROGRAM_ERROR; // Propagate some err
             }
             return NULL;
@@ -913,7 +922,7 @@ Calendar::makeInstance(const Locale& aLocale, UErrorCode& success) {
 
         str = dynamic_cast<const UnicodeString*>(c);
         if(str != NULL) {
-            // recursed! Second lookup returned a UnicodeString. 
+            // recursed! Second lookup returned a UnicodeString.
             // Perhaps DefaultCalendar{} was set to another locale.
 #ifdef U_DEBUG_CALSVC
             char tmp[200];
@@ -987,7 +996,7 @@ Calendar::createInstance(const TimeZone& zone, const Locale& aLocale, UErrorCode
     if(U_SUCCESS(success) && c) {
         c->setTimeZone(zone);
     }
-    return c; 
+    return c;
 }
 
 // -------------------------------------
@@ -1019,7 +1028,7 @@ Calendar::operator==(const Calendar& that) const
         U_SUCCESS(status);
 }
 
-UBool 
+UBool
 Calendar::isEquivalentTo(const Calendar& other) const
 {
     return typeid(*this) == typeid(other) &&
@@ -1101,13 +1110,13 @@ Calendar::getNow()
 * Gets this Calendar's current time as a long.
 * @return the current time as UTC milliseconds from the epoch.
 */
-double 
+double
 Calendar::getTimeInMillis(UErrorCode& status) const
 {
-    if(U_FAILURE(status)) 
+    if(U_FAILURE(status))
         return 0.0;
 
-    if ( ! fIsTimeSet) 
+    if ( ! fIsTimeSet)
         ((Calendar*)this)->updateTime(status);
 
     /* Test for buffer overflows */
@@ -1126,9 +1135,9 @@ Calendar::getTimeInMillis(UErrorCode& status) const
 * when in lenient mode the out of range values are pinned to their respective min/max.
 * @param date the new time in UTC milliseconds from the epoch.
 */
-void 
+void
 Calendar::setTimeInMillis( double millis, UErrorCode& status ) {
-    if(U_FAILURE(status)) 
+    if(U_FAILURE(status))
         return;
 
     if (millis > MAX_MILLIS) {
@@ -1156,7 +1165,7 @@ Calendar::setTimeInMillis( double millis, UErrorCode& status ) {
         fStamp[i]     = kUnset;
         fIsSet[i]     = FALSE;
     }
-    
+
 
 }
 
@@ -1493,7 +1502,7 @@ void Calendar::computeFields(UErrorCode &ec)
     double localMillis = internalGetTime();
     int32_t rawOffset, dstOffset;
     getTimeZone().getOffset(localMillis, FALSE, rawOffset, dstOffset, ec);
-    localMillis += (rawOffset + dstOffset); 
+    localMillis += (rawOffset + dstOffset);
 
     // Mark fields as set.  Do this before calling handleComputeFields().
     uint32_t mask =   //fInternalSetMask;
@@ -1502,7 +1511,7 @@ void Calendar::computeFields(UErrorCode &ec)
         (1 << UCAL_MONTH) |
         (1 << UCAL_DAY_OF_MONTH) | // = UCAL_DATE
         (1 << UCAL_DAY_OF_YEAR) |
-        (1 << UCAL_EXTENDED_YEAR);  
+        (1 << UCAL_EXTENDED_YEAR);
 
     for (int32_t i=0; i<UCAL_FIELD_COUNT; ++i) {
         if ((mask & 1) == 0) {
@@ -1531,7 +1540,7 @@ void Calendar::computeFields(UErrorCode &ec)
 #if defined (U_DEBUG_CAL)
     //fprintf(stderr, "%s:%d- Hmm! Jules @ %d, as per %.0lf millis\n",
     //__FILE__, __LINE__, fFields[UCAL_JULIAN_DAY], localMillis);
-#endif  
+#endif
 
     computeGregorianAndDOWFields(fFields[UCAL_JULIAN_DAY], ec);
 
@@ -1629,7 +1638,7 @@ void Calendar::computeGregorianFields(int32_t julianDay, UErrorCode & /* ec */)
 * proleptic Gregorian calendar, which has no field larger than a year.
 */
 void Calendar::computeWeekFields(UErrorCode &ec) {
-    if(U_FAILURE(ec)) { 
+    if(U_FAILURE(ec)) {
         return;
     }
     int32_t eyear = fFields[UCAL_EXTENDED_YEAR];
@@ -1692,7 +1701,7 @@ void Calendar::computeWeekFields(UErrorCode &ec) {
     fFields[UCAL_WEEK_OF_MONTH] = weekNumber(dayOfMonth, dayOfWeek);
     fFields[UCAL_DAY_OF_WEEK_IN_MONTH] = (dayOfMonth-1) / 7 + 1;
 #if defined (U_DEBUG_CAL)
-    if(fFields[UCAL_DAY_OF_WEEK_IN_MONTH]==0) fprintf(stderr, "%s:%d: DOWIM %d on %g\n", 
+    if(fFields[UCAL_DAY_OF_WEEK_IN_MONTH]==0) fprintf(stderr, "%s:%d: DOWIM %d on %g\n",
         __FILE__, __LINE__,fFields[UCAL_DAY_OF_WEEK_IN_MONTH], fTime);
 #endif
 }
@@ -1737,7 +1746,7 @@ void Calendar::handleComputeFields(int32_t /* julianDay */, UErrorCode &/* statu
 // -------------------------------------
 
 
-void Calendar::roll(EDateFields field, int32_t amount, UErrorCode& status) 
+void Calendar::roll(EDateFields field, int32_t amount, UErrorCode& status)
 {
     roll((UCalendarDateFields)field, amount, status);
 }
@@ -2075,7 +2084,7 @@ void Calendar::roll(UCalendarDateFields field, int32_t amount, UErrorCode& statu
     default:
         // Other fields cannot be rolled by this method
 #if defined (U_DEBUG_CAL)
-        fprintf(stderr, "%s:%d: ILLEGAL ARG because of roll on non-rollable field %s\n", 
+        fprintf(stderr, "%s:%d: ILLEGAL ARG because of roll on non-rollable field %s\n",
             __FILE__, __LINE__,fldName(field));
 #endif
         status = U_ILLEGAL_ARGUMENT_ERROR;
@@ -2143,6 +2152,7 @@ void Calendar::add(UCalendarDateFields field, int32_t amount, UErrorCode& status
         }
       }
       // Fall through into normal handling
+      U_FALLTHROUGH;
     case UCAL_EXTENDED_YEAR:
     case UCAL_MONTH:
       {
@@ -2265,7 +2275,7 @@ void Calendar::add(UCalendarDateFields field, int32_t amount, UErrorCode& status
                 }
             }
         }
-    } 
+    }
 }
 
 // -------------------------------------
@@ -2619,6 +2629,7 @@ Calendar::isWeekend(void) const
                             (millisInDay <  transitionMillis);
                     }
                     // else fall through, return FALSE
+                    U_FALLTHROUGH;
                 }
             default:
                 break;
@@ -2629,7 +2640,7 @@ Calendar::isWeekend(void) const
 
 // ------------------------------------- limits
 
-int32_t 
+int32_t
 Calendar::getMinimum(EDateFields field) const {
     return getLimit((UCalendarDateFields) field,UCAL_LIMIT_MINIMUM);
 }
@@ -2680,7 +2691,7 @@ Calendar::getLeastMaximum(UCalendarDateFields field) const
 }
 
 // -------------------------------------
-int32_t 
+int32_t
 Calendar::getActualMinimum(EDateFields field, UErrorCode& status) const
 {
     return getActualMinimum((UCalendarDateFields) field, status);
@@ -2756,7 +2767,7 @@ Calendar::getActualMinimum(UCalendarDateFields field, UErrorCode& status) const
         work->set(field, fieldValue);
         if (work->get(field, status) != fieldValue) {
             break;
-        } 
+        }
         else {
             result = fieldValue;
             fieldValue--;
@@ -2812,7 +2823,7 @@ void Calendar::validateField(UCalendarDateFields field, UErrorCode &status) {
     case UCAL_DAY_OF_WEEK_IN_MONTH:
         if (internalGet(field) == 0) {
 #if defined (U_DEBUG_CAL)
-            fprintf(stderr, "%s:%d: ILLEGAL ARG because DOW in month cannot be 0\n", 
+            fprintf(stderr, "%s:%d: ILLEGAL ARG because DOW in month cannot be 0\n",
                 __FILE__, __LINE__);
 #endif
             status = U_ILLEGAL_ARGUMENT_ERROR; // "DAY_OF_WEEK_IN_MONTH cannot be zero"
@@ -2838,7 +2849,7 @@ void Calendar::validateField(UCalendarDateFields field, int32_t min, int32_t max
     int32_t value = fFields[field];
     if (value < min || value > max) {
 #if defined (U_DEBUG_CAL)
-        fprintf(stderr, "%s:%d: ILLEGAL ARG because of field %s out of range %d..%d  at %d\n", 
+        fprintf(stderr, "%s:%d: ILLEGAL ARG because of field %s out of range %d..%d  at %d\n",
             __FILE__, __LINE__,fldName(field),min,max,value);
 #endif
         status = U_ILLEGAL_ARGUMENT_ERROR;
@@ -2935,7 +2946,7 @@ linesInGroup:
 }
 
 const UFieldResolutionTable Calendar::kDatePrecedence[] =
-{ 
+{
     {
         { UCAL_DAY_OF_MONTH, kResolveSTOP },
         { UCAL_WEEK_OF_YEAR, UCAL_DAY_OF_WEEK, kResolveSTOP },
@@ -2956,12 +2967,12 @@ const UFieldResolutionTable Calendar::kDatePrecedence[] =
         { kResolveRemap | UCAL_DAY_OF_WEEK_IN_MONTH, UCAL_DAY_OF_WEEK, kResolveSTOP },
         { kResolveRemap | UCAL_DAY_OF_WEEK_IN_MONTH, UCAL_DOW_LOCAL, kResolveSTOP },
         { kResolveSTOP }
-    }, 
+    },
     {{kResolveSTOP}}
 };
 
 
-const UFieldResolutionTable Calendar::kDOWPrecedence[] = 
+const UFieldResolutionTable Calendar::kDOWPrecedence[] =
 {
     {
         { UCAL_DAY_OF_WEEK,kResolveSTOP, kResolveSTOP },
@@ -2972,7 +2983,7 @@ const UFieldResolutionTable Calendar::kDOWPrecedence[] =
 };
 
 // precedence for calculating a year
-const UFieldResolutionTable Calendar::kYearPrecedence[] = 
+const UFieldResolutionTable Calendar::kYearPrecedence[] =
 {
     {
         { UCAL_YEAR, kResolveSTOP },
@@ -3009,7 +3020,7 @@ void Calendar::computeTime(UErrorCode& status) {
     //  }
 #endif
 
-    int32_t millisInDay;
+    double millisInDay;
 
     // We only use MILLISECONDS_IN_DAY if it has been set by the user.
     // This makes it possible for the caller to set the calendar to a
@@ -3129,10 +3140,10 @@ UBool Calendar::getImmediatePreviousZoneTransition(UDate base, UDate *transition
 * reflects local zone wall time.
 * @stable ICU 2.0
 */
-int32_t Calendar::computeMillisInDay() {
+double Calendar::computeMillisInDay() {
   // Do the time portion of the conversion.
 
-    int32_t millisInDay = 0;
+    double millisInDay = 0;
 
     // Find the best set of fields specifying the time of day.  There
     // are only two possibilities here; the HOUR_OF_DAY or the
@@ -3174,7 +3185,7 @@ int32_t Calendar::computeMillisInDay() {
 * or range.
 * @stable ICU 2.0
 */
-int32_t Calendar::computeZoneOffset(double millis, int32_t millisInDay, UErrorCode &ec) {
+int32_t Calendar::computeZoneOffset(double millis, double millisInDay, UErrorCode &ec) {
     int32_t rawOffset, dstOffset;
     UDate wall = millis + millisInDay;
     BasicTimeZone* btz = getBasicTimeZone();
@@ -3221,7 +3232,7 @@ int32_t Calendar::computeZoneOffset(double millis, int32_t millisInDay, UErrorCo
     return rawOffset + dstOffset;
 }
 
-int32_t Calendar::computeJulianDay() 
+int32_t Calendar::computeJulianDay()
 {
     // We want to see if any of the date fields is newer than the
     // JULIAN_DAY.  If not, then we use JULIAN_DAY.  If so, then we do
@@ -3255,17 +3266,17 @@ int32_t Calendar::handleComputeJulianDay(UCalendarDateFields bestField)  {
         bestField == UCAL_DAY_OF_WEEK_IN_MONTH);
     int32_t year;
 
-    if (bestField == UCAL_WEEK_OF_YEAR) {
-        year = internalGet(UCAL_YEAR_WOY, handleGetExtendedYear());
-        internalSet(UCAL_EXTENDED_YEAR, year);
+    if (bestField == UCAL_WEEK_OF_YEAR && newerField(UCAL_YEAR_WOY, UCAL_YEAR) == UCAL_YEAR_WOY) {
+        year = internalGet(UCAL_YEAR_WOY);
     } else {
         year = handleGetExtendedYear();
-        internalSet(UCAL_EXTENDED_YEAR, year);
     }
 
-#if defined (U_DEBUG_CAL) 
+    internalSet(UCAL_EXTENDED_YEAR, year);
+
+#if defined (U_DEBUG_CAL)
     fprintf(stderr, "%s:%d: bestField= %s - y=%d\n", __FILE__, __LINE__, fldName(bestField), year);
-#endif 
+#endif
 
     // Get the Julian day of the day BEFORE the start of this year.
     // If useMonth is true, get the day before the start of the month.
@@ -3347,9 +3358,9 @@ int32_t Calendar::handleComputeJulianDay(UCalendarDateFields bestField)  {
             date += ((monthLength - date) / 7 + dim + 1) * 7;
         }
     } else {
-#if defined (U_DEBUG_CAL) 
+#if defined (U_DEBUG_CAL)
         fprintf(stderr, "%s:%d - bf= %s\n", __FILE__, __LINE__, fldName(bestField));
-#endif 
+#endif
 
         if(bestField == UCAL_WEEK_OF_YEAR) {  // ------------------------------------- WOY -------------
             if(!isSet(UCAL_YEAR_WOY) ||  // YWOY not set at all or
@@ -3360,30 +3371,30 @@ int32_t Calendar::handleComputeJulianDay(UCalendarDateFields bestField)  {
                 int32_t woy = internalGet(bestField);
 
                 int32_t nextJulianDay = handleComputeMonthStart(year+1, 0, FALSE); // jd of day before jan 1
-                int32_t nextFirst = julianDayToDayOfWeek(nextJulianDay + 1) - firstDayOfWeek; 
+                int32_t nextFirst = julianDayToDayOfWeek(nextJulianDay + 1) - firstDayOfWeek;
 
                 if (nextFirst < 0) { // 0..6 ldow of Jan 1
                     nextFirst += 7;
                 }
 
                 if(woy==1) {  // FIRST WEEK ---------------------------------
-#if defined (U_DEBUG_CAL) 
-                    fprintf(stderr, "%s:%d - woy=%d, yp=%d, nj(%d)=%d, nf=%d", __FILE__, __LINE__, 
-                        internalGet(bestField), resolveFields(kYearPrecedence), year+1, 
+#if defined (U_DEBUG_CAL)
+                    fprintf(stderr, "%s:%d - woy=%d, yp=%d, nj(%d)=%d, nf=%d", __FILE__, __LINE__,
+                        internalGet(bestField), resolveFields(kYearPrecedence), year+1,
                         nextJulianDay, nextFirst);
 
                     fprintf(stderr, " next: %d DFW,  min=%d   \n", (7-nextFirst), getMinimalDaysInFirstWeek() );
-#endif 
+#endif
 
                     // nextFirst is now the localized DOW of Jan 1  of y-woy+1
                     if((nextFirst > 0) &&   // Jan 1 starts on FDOW
                         (7-nextFirst) >= getMinimalDaysInFirstWeek()) // or enough days in the week
                     {
                         // Jan 1 of (yearWoy+1) is in yearWoy+1 - recalculate JD to next year
-#if defined (U_DEBUG_CAL) 
-                        fprintf(stderr, "%s:%d - was going to move JD from %d to %d [d%d]\n", __FILE__, __LINE__, 
+#if defined (U_DEBUG_CAL)
+                        fprintf(stderr, "%s:%d - was going to move JD from %d to %d [d%d]\n", __FILE__, __LINE__,
                             julianDay, nextJulianDay, (nextJulianDay-julianDay));
-#endif 
+#endif
                         julianDay = nextJulianDay;
 
                         // recalculate 'first' [0-based local dow of jan 1]
@@ -3394,7 +3405,7 @@ int32_t Calendar::handleComputeJulianDay(UCalendarDateFields bestField)  {
                         // recalculate date.
                         date = 1 - first + dowLocal;
                     }
-                } else if(woy>=getLeastMaximum(bestField)) {          
+                } else if(woy>=getLeastMaximum(bestField)) {
                     // could be in the last week- find out if this JD would overstep
                     int32_t testDate = date;
                     if ((7 - first) < getMinimalDaysInFirstWeek()) {
@@ -3404,7 +3415,7 @@ int32_t Calendar::handleComputeJulianDay(UCalendarDateFields bestField)  {
                     // Now adjust for the week number.
                     testDate += 7 * (woy - 1);
 
-#if defined (U_DEBUG_CAL) 
+#if defined (U_DEBUG_CAL)
                     fprintf(stderr, "%s:%d - y=%d, y-1=%d doy%d, njd%d (C.F. %d)\n",
                         __FILE__, __LINE__, year, year-1, testDate, julianDay+testDate, nextJulianDay);
 #endif
@@ -3418,7 +3429,7 @@ int32_t Calendar::handleComputeJulianDay(UCalendarDateFields bestField)  {
                         }
                         date = 1 - first + dowLocal;
 
-#if defined (U_DEBUG_CAL) 
+#if defined (U_DEBUG_CAL)
                         fprintf(stderr, "%s:%d - date now %d, jd%d, ywoy%d\n",
                             __FILE__, __LINE__, date, julianDay, year-1);
 #endif
@@ -3443,13 +3454,13 @@ int32_t Calendar::handleComputeJulianDay(UCalendarDateFields bestField)  {
 }
 
 int32_t
-Calendar::getDefaultMonthInYear(int32_t /*eyear*/) 
+Calendar::getDefaultMonthInYear(int32_t /*eyear*/)
 {
     return 0;
 }
 
 int32_t
-Calendar::getDefaultDayInMonth(int32_t /*eyear*/, int32_t /*month*/) 
+Calendar::getDefaultDayInMonth(int32_t /*eyear*/, int32_t /*month*/)
 {
     return 1;
 }
@@ -3479,13 +3490,13 @@ int32_t Calendar::getLocalDOW()
 
 int32_t Calendar::handleGetExtendedYearFromWeekFields(int32_t yearWoy, int32_t woy)
 {
-    // We have UCAL_YEAR_WOY and UCAL_WEEK_OF_YEAR - from those, determine 
+    // We have UCAL_YEAR_WOY and UCAL_WEEK_OF_YEAR - from those, determine
     // what year we fall in, so that other code can set it properly.
     // (code borrowed from computeWeekFields and handleComputeJulianDay)
     //return yearWoy;
 
     // First, we need a reliable DOW.
-    UCalendarDateFields bestField = resolveFields(kDatePrecedence); // !! Note: if subclasses have a different table, they should override handleGetExtendedYearFromWeekFields 
+    UCalendarDateFields bestField = resolveFields(kDatePrecedence); // !! Note: if subclasses have a different table, they should override handleGetExtendedYearFromWeekFields
 
     // Now, a local DOW
     int32_t dowLocal = getLocalDOW(); // 0..6
@@ -3518,9 +3529,9 @@ int32_t Calendar::handleGetExtendedYearFromWeekFields(int32_t yearWoy, int32_t w
 
     int32_t minDays = getMinimalDaysInFirstWeek();
     UBool jan1InPrevYear = FALSE;  // January 1st in the year of WOY is the 1st week?  (i.e. first week is < minimal )
-    //UBool nextJan1InPrevYear = FALSE; // January 1st of Year of WOY + 1 is in the first week? 
+    //UBool nextJan1InPrevYear = FALSE; // January 1st of Year of WOY + 1 is in the first week?
 
-    if((7 - first) < minDays) { 
+    if((7 - first) < minDays) {
         jan1InPrevYear = TRUE;
     }
 
@@ -3543,8 +3554,8 @@ int32_t Calendar::handleGetExtendedYearFromWeekFields(int32_t yearWoy, int32_t w
                     return yearWoy; // in this year
                 }
             }
-        } else if(woy >= getLeastMaximum(bestField)) {  
-            // we _might_ be in the last week.. 
+        } else if(woy >= getLeastMaximum(bestField)) {
+            // we _might_ be in the last week..
             int32_t jd =  // Calculate JD of our target day:
                 jan1Start +  // JD of Jan 1
                 (7-first) + //  days in the first week (Jan 1.. )
@@ -3581,7 +3592,7 @@ int32_t Calendar::handleGetExtendedYearFromWeekFields(int32_t yearWoy, int32_t w
             }
 
             //(internalGet(UCAL_DATE) <= (7-first)) /* && in minDow  */ ) {
-            //within 1st week and in this month.. 
+            //within 1st week and in this month..
             //return yearWoy+1;
             return yearWoy;
 
@@ -3688,7 +3699,7 @@ void Calendar::prepareGetActual(UCalendarDateFields field, UBool isMinimum, UErr
 
     case UCAL_YEAR_WOY:
         set(UCAL_WEEK_OF_YEAR, getGreatestMinimum(UCAL_WEEK_OF_YEAR));
-
+        U_FALLTHROUGH;
     case UCAL_MONTH:
         set(UCAL_DATE, getGreatestMinimum(UCAL_DATE));
         break;
@@ -3714,7 +3725,7 @@ void Calendar::prepareGetActual(UCalendarDateFields field, UBool isMinimum, UErr
                     dow += 7;
                 }
             }
-#if defined (U_DEBUG_CAL) 
+#if defined (U_DEBUG_CAL)
             fprintf(stderr, "prepareGetActualHelper(WOM/WOY) - dow=%d\n", dow);
 #endif
             set(UCAL_DAY_OF_WEEK, dow);
@@ -3730,7 +3741,7 @@ void Calendar::prepareGetActual(UCalendarDateFields field, UBool isMinimum, UErr
 
 int32_t Calendar::getActualHelper(UCalendarDateFields field, int32_t startValue, int32_t endValue, UErrorCode &status) const
 {
-#if defined (U_DEBUG_CAL) 
+#if defined (U_DEBUG_CAL)
     fprintf(stderr, "getActualHelper(%d,%d .. %d, %s)\n", field, startValue, endValue, u_errorName(status));
 #endif
     if (startValue == endValue) {
@@ -3766,7 +3777,7 @@ int32_t Calendar::getActualHelper(UCalendarDateFields field, int32_t startValue,
     int32_t result = startValue;
     if ((work->get(field, status) != startValue
          && field != UCAL_WEEK_OF_MONTH && delta > 0 ) || U_FAILURE(status)) {
-#if defined (U_DEBUG_CAL) 
+#if defined (U_DEBUG_CAL)
         fprintf(stderr, "getActualHelper(fld %d) - got  %d (not %d) - %s\n", field, work->get(field,status), startValue, u_errorName(status));
 #endif
     } else {
@@ -3783,7 +3794,7 @@ int32_t Calendar::getActualHelper(UCalendarDateFields field, int32_t startValue,
         } while (startValue != endValue);
     }
     delete work;
-#if defined (U_DEBUG_CAL) 
+#if defined (U_DEBUG_CAL)
     fprintf(stderr, "getActualHelper(%d) = %d\n", field, result);
 #endif
     return result;
@@ -3810,18 +3821,18 @@ Calendar::setWeekData(const Locale& desiredLocale, const char *type, UErrorCode&
     // Since week and weekend data is territory based instead of language based,
     // we may need to tweak the locale that we are using to try to get the appropriate
     // values, using the following logic:
-    // 1). If the locale has a language but no territory, use the territory as defined by 
+    // 1). If the locale has a language but no territory, use the territory as defined by
     //     the likely subtags.
     // 2). If the locale has a script designation then we ignore it,
     //     then remove it ( i.e. "en_Latn_US" becomes "en_US" )
+
     char minLocaleID[ULOC_FULLNAME_CAPACITY] = { 0 };
     UErrorCode myStatus = U_ZERO_ERROR;
 
     uloc_minimizeSubtags(desiredLocale.getName(),minLocaleID,ULOC_FULLNAME_CAPACITY,&myStatus);
     Locale min = Locale::createFromName(minLocaleID);
     Locale useLocale;
-    if ( uprv_strlen(desiredLocale.getCountry()) == 0 || 
+    if ( uprv_strlen(desiredLocale.getCountry()) == 0 ||
          (uprv_strlen(desiredLocale.getScript()) > 0 && uprv_strlen(min.getScript()) == 0) ) {
         char maxLocaleID[ULOC_FULLNAME_CAPACITY] = { 0 };
         myStatus = U_ZERO_ERROR;
@@ -3831,38 +3842,55 @@ Calendar::setWeekData(const Locale& desiredLocale, const char *type, UErrorCode&
     } else {
         useLocale = Locale(desiredLocale);
     }
-    /* The code here is somewhat of a hack, since week data and weekend data aren't really tied to 
+
+    /* The code here is somewhat of a hack, since week data and weekend data aren't really tied to
        a specific calendar, they aren't truly locale data.  But this is the only place where valid and
        actual locale can be set, so we take a shot at it here by loading a representative resource
        from the calendar data.  The code used to use the dateTimeElements resource to get first day
        of week data, but this was moved to supplemental data under ticket 7755. (JCE) */
 
-    CalendarData calData(useLocale,type,status);
-    UResourceBundle *monthNames = calData.getByKey(gMonthNames,status);
+    // Get the monthNames resource bundle for the calendar 'type'. Fallback to gregorian if the resource is not
+    // found.
+    LocalUResourceBundlePointer calData(ures_open(NULL, useLocale.getBaseName(), &status));
+    ures_getByKey(calData.getAlias(), gCalendar, calData.getAlias(), &status);
+
+    LocalUResourceBundlePointer monthNames;
+    if (type != NULL && *type != '\0' && uprv_strcmp(type, gGregorian) != 0) {
+        monthNames.adoptInstead(ures_getByKeyWithFallback(calData.getAlias(), type, NULL, &status));
+        ures_getByKeyWithFallback(monthNames.getAlias(), gMonthNames,
+                                  monthNames.getAlias(), &status);
+    }
+
+    if (monthNames.isNull() || status == U_MISSING_RESOURCE_ERROR) {
+        status = U_ZERO_ERROR;
+        monthNames.adoptInstead(ures_getByKeyWithFallback(calData.getAlias(), gGregorian,
+                                                          monthNames.orphan(), &status));
+        ures_getByKeyWithFallback(monthNames.getAlias(), gMonthNames,
+                                  monthNames.getAlias(), &status);
+    }
+
     if (U_SUCCESS(status)) {
         U_LOCALE_BASED(locBased,*this);
-        locBased.setLocaleIDs(ures_getLocaleByType(monthNames, ULOC_VALID_LOCALE, &status),
-                              ures_getLocaleByType(monthNames, ULOC_ACTUAL_LOCALE, &status));
+        locBased.setLocaleIDs(ures_getLocaleByType(monthNames.getAlias(), ULOC_VALID_LOCALE, &status),
+                              ures_getLocaleByType(monthNames.getAlias(), ULOC_ACTUAL_LOCALE, &status));
     } else {
         status = U_USING_FALLBACK_WARNING;
         return;
     }
 
-    
+    char region[ULOC_COUNTRY_CAPACITY];
+    (void)ulocimp_getRegionForSupplementalData(desiredLocale.getName(), TRUE, region, sizeof(region), &status);
+
     // Read week data values from supplementalData week data
     UResourceBundle *rb = ures_openDirect(NULL, "supplementalData", &status);
     ures_getByKey(rb, "weekData", rb, &status);
-    UResourceBundle *weekData = ures_getByKey(rb, useLocale.getCountry(), NULL, &status);
+    UResourceBundle *weekData = ures_getByKey(rb, region, NULL, &status);
     if (status == U_MISSING_RESOURCE_ERROR && rb != NULL) {
         status = U_ZERO_ERROR;
         weekData = ures_getByKey(rb, "001", NULL, &status);
     }
 
     if (U_FAILURE(status)) {
-#if defined (U_DEBUG_CALDATA)
-        fprintf(stderr, " Failure loading weekData from supplemental = %s\n", u_errorName(status));
-#endif
         status = U_USING_FALLBACK_WARNING;
     } else {
         int32_t arrLen;
@@ -3891,8 +3919,8 @@ Calendar::setWeekData(const Locale& desiredLocale, const char *type, UErrorCode&
 * and areFieldsSet.  Callers should check isTimeSet and only
 * call this method if isTimeSet is false.
 */
-void 
-Calendar::updateTime(UErrorCode& status) 
+void
+Calendar::updateTime(UErrorCode& status)
 {
     computeTime(status);
     if(U_FAILURE(status))
@@ -3901,14 +3929,14 @@ Calendar::updateTime(UErrorCode& status)
     // If we are lenient, we need to recompute the fields to normalize
     // the values.  Also, if we haven't set all the fields yet (i.e.,
     // in a newly-created object), we need to fill in the fields. [LIU]
-    if (isLenient() || ! fAreAllFieldsSet) 
+    if (isLenient() || ! fAreAllFieldsSet)
         fAreFieldsSet = FALSE;
 
     fIsTimeSet = TRUE;
     fAreFieldsVirtuallySet = FALSE;
 }
 
-Locale 
+Locale
 Calendar::getLocale(ULocDataLocaleType type, UErrorCode& status) const {
     U_LOCALE_BASED(locBased, *this);
     return locBased.getLocale(type, status);
@@ -3971,4 +3999,3 @@ U_NAMESPACE_END
 
 
 //eof
-