+UnicodeString
+SimpleDateFormat::getPatternForTimeStyle(EStyle timeStyle,
+ const Locale& locale,
+ UResourceBundle* dateTimePatterns,
+ UnicodeString& ovrStr,
+ UErrorCode& status) {
+ UnicodeString timePattern;
+ if (timeStyle >= kFull && timeStyle <= kShort) {
+ const char* baseLoc = locale.getBaseName();
+ if (baseLoc!=NULL && baseLoc[0]!=0 && uprv_strcmp(baseLoc,"und")!=0) {
+ UErrorCode useStatus = U_ZERO_ERROR;
+ const char* validLoc = getLocaleID(ULOC_VALID_LOCALE, useStatus);
+ if (U_SUCCESS(useStatus) && uprv_strcmp(validLoc,baseLoc)!=0) {
+ char minLoc[kBaseNameMax];
+ uloc_minimizeSubtags(baseLoc, minLoc, kBaseNameMax, &useStatus);
+ minLoc[kBaseNameMax-1] = 0; // ensure zero term
+ const char* actualLoc = getLocaleID(ULOC_ACTUAL_LOCALE, useStatus);
+ if (U_SUCCESS(useStatus) && uprv_strcmp(actualLoc,minLoc)!=0) {
+ // The standard time formats may have the wrong time cycle, because:
+ // * the valid locale is not the same as the base locale, or
+ // * the actual locale the patterns are coming from is not the same
+ // as the minimized locale.
+ // We could *also* check whether they do actually have a mismatch with
+ // the time cycle preferences for the region, but that is a lot more
+ // work for little or no additional benefit, since just going ahead
+ // and always synthesizing the time format as per the following should
+ // create a locale-appropriate pattern with cycle that matches the
+ // region preferences anyway (for completely unsupported languages,
+ // this will use root patterns for the appropriate cycle for the
+ // likely subtags resion).
+ LocalPointer<DateTimePatternGenerator> dtpg(DateTimePatternGenerator::createInstance(locale, useStatus, TRUE));
+ if (U_SUCCESS(useStatus)) {
+ UnicodeString timeSkeleton(TRUE, timeSkeletons[timeStyle], -1);
+ timePattern = dtpg->getBestPattern(timeSkeleton, useStatus);
+#if DEBUG_SYNTHETIC_TIMEFMTS
+ if (timePattern.length() != 0) {
+ char bbuf[32];
+ timePattern.extract(0,timePattern.length(),bbuf,32);
+ printf("\n## for locale %s, validLoc %s, minLoc %s, actualLoc %s, synth timePat %s\n", locale.getName(), validLoc, minLoc, actualLoc, bbuf);
+ }
+#endif
+ }
+ }
+ }
+ }
+ }
+
+ if (timePattern.isEmpty()) {
+ timePattern = getPatternString((int32_t)timeStyle, dateTimePatterns, ovrStr, status);
+ }
+ return timePattern;
+}
+
+UnicodeString
+SimpleDateFormat::getPatternForDateStyle(EStyle dateStyle,
+ UResourceBundle* languageDateTimePatterns,
+ UResourceBundle* countryDateTimePatterns,
+ UBool& fallingBackByCountry,
+ UnicodeString& ovrStr,
+ UErrorCode& status) {
+ UnicodeString languageOverride;
+ UnicodeString languagePattern = getPatternString((int32_t)dateStyle, languageDateTimePatterns, languageOverride, status);
+
+ // by default, we should fetch the pattern from the language resource
+ UnicodeString result = languagePattern;
+ ovrStr = languageOverride;
+
+ // but IF the country resource is actually different from the lanuguage resource AND the caller is asking
+ // for a medium or short date format AND that format in the country resource is all-numeric, return the
+ // pattern from the country resource instead
+ if (fallingBackByCountry) {
+ fallingBackByCountry = FALSE;
+ if ((dateStyle == kDateOffset + kMedium || dateStyle == kDateOffset + kShort)) {
+ UnicodeString countryOverride;
+ UnicodeString countryPattern = getPatternString((int32_t)dateStyle, countryDateTimePatterns, countryOverride, status);
+ UBool stripRTLmarks = uloc_isRightToLeft(ures_getLocaleByType(countryDateTimePatterns, ULOC_ACTUAL_LOCALE, &status)) && !uloc_isRightToLeft(ures_getLocaleByType(languageDateTimePatterns, ULOC_ACTUAL_LOCALE, &status));
+
+ if (U_SUCCESS(status)) {
+ if (datePatternHasNumericCore(countryPattern)) {
+ ovrStr = countryOverride;
+ result = countryPattern;
+ fallingBackByCountry = TRUE;
+ if (stripRTLmarks) {
+ // the date formats for RTL languages often include Unicode right-to-left marks to get the format
+ // to lay out correctly. If we got the pattern from a RTL locale and the requested language is
+ // not a RTL language, we need to strip those out (same comment below)
+ result.findAndReplace(UnicodeString(u'\u200f'), UnicodeString());
+ }
+ } else if (dateStyle == kDateOffset + kMedium && datePatternHasNumericCore(languagePattern)) {
+ // if the user asked for the MEDIUM format, it's NOT all-numeric in the country resource, but it IS
+ // all-numeric in the language resource, return the SHORT format from the country resource
+ countryPattern = getPatternString(kDateOffset + kShort, countryDateTimePatterns, countryOverride, status);
+ if (datePatternHasNumericCore(countryPattern)) {
+ ovrStr = countryOverride;
+ result = countryPattern;
+ fallingBackByCountry = TRUE;
+ if (stripRTLmarks) {
+ result.findAndReplace(UnicodeString(u'\u200f'), UnicodeString());
+ }
+ }
+ }
+ }
+ }
+ }
+ return result;
+}
+
+UnicodeString
+SimpleDateFormat::getPatternString(int32_t index,
+ UResourceBundle* dateTimePatterns,
+ UnicodeString& ovrStr,
+ UErrorCode& status) {
+ UnicodeString resStr;
+ LocalUResourceBundlePointer currentBundle(ures_getByIndex(dateTimePatterns, index, NULL, &status));
+ ovrStr.remove();
+ if (U_FAILURE(status)) {
+ status = U_INVALID_FORMAT_ERROR;
+ return resStr;
+ }
+ switch (ures_getType(currentBundle.getAlias())) {
+ case URES_STRING: {
+ resStr = ures_getUnicodeString(currentBundle.getAlias(), &status);
+ break;
+ }
+ case URES_ARRAY: {
+ resStr = ures_getUnicodeStringByIndex(currentBundle.getAlias(), 0, &status);
+ ovrStr = ures_getUnicodeStringByIndex(currentBundle.getAlias(), 1, &status);
+ break;
+ }
+ default: {
+ status = U_INVALID_FORMAT_ERROR;
+ return resStr;
+ }
+ }
+ return resStr;
+}
+