# Handle 'O' time zone skeleton in DateIntervalFormat. # Keep time zone skeleton field widths in DateIntervalFormat. # # ICU bug: https://unicode-org.atlassian.net/browse/ICU-20548 diff --git a/intl/icu/source/i18n/dtitv_impl.h b/intl/icu/source/i18n/dtitv_impl.h --- a/intl/icu/source/i18n/dtitv_impl.h +++ b/intl/icu/source/i18n/dtitv_impl.h @@ -84,16 +84,19 @@ #define CAP_W ((char16_t)0x0057) #define CAP_Y ((char16_t)0x0059) #define CAP_Z ((char16_t)0x005A) //#define MINIMUM_SUPPORTED_CALENDAR_FIELD UCAL_MINUTE #define MAX_E_COUNT 5 #define MAX_M_COUNT 5 +#define MAX_z_COUNT 4 +#define MAX_v_COUNT 4 +#define MAX_O_COUNT 4 //#define MAX_INTERVAL_INDEX 4 #define MAX_POSITIVE_INT 56632 #endif /* #if !UCONFIG_NO_FORMATTING */ #endif //eof diff --git a/intl/icu/source/i18n/dtitvfmt.cpp b/intl/icu/source/i18n/dtitvfmt.cpp --- a/intl/icu/source/i18n/dtitvfmt.cpp +++ b/intl/icu/source/i18n/dtitvfmt.cpp @@ -1061,16 +1061,17 @@ DateIntervalFormat::getDateTimeSkeleton( // timeSkeleton follows the sequence of hm*[v|z]? int32_t ECount = 0; int32_t dCount = 0; int32_t MCount = 0; int32_t yCount = 0; int32_t mCount = 0; int32_t vCount = 0; int32_t zCount = 0; + int32_t OCount = 0; char16_t hourChar = u'\0'; int32_t i; for (i = 0; i < skeleton.length(); ++i) { char16_t ch = skeleton[i]; switch ( ch ) { case CAP_E: dateSkeleton.append(ch); @@ -1123,16 +1124,20 @@ DateIntervalFormat::getDateTimeSkeleton( case LOW_Z: ++zCount; timeSkeleton.append(ch); break; case LOW_V: ++vCount; timeSkeleton.append(ch); break; + case CAP_O: + ++OCount; + timeSkeleton.append(ch); + break; case LOW_A: case CAP_V: case CAP_Z: case LOW_J: case LOW_S: case CAP_S: case CAP_A: case LOW_B: @@ -1174,20 +1179,41 @@ DateIntervalFormat::getDateTimeSkeleton( /* generate normalized form for time */ if ( hourChar != u'\0' ) { normalizedTimeSkeleton.append(hourChar); } if ( mCount != 0 ) { normalizedTimeSkeleton.append(LOW_M); } if ( zCount != 0 ) { - normalizedTimeSkeleton.append(LOW_Z); + if ( zCount <= 3 ) { + normalizedTimeSkeleton.append(LOW_Z); + } else { + for ( int32_t j = 0; j < zCount && j < MAX_z_COUNT; ++j ) { + normalizedTimeSkeleton.append(LOW_Z); + } + } } if ( vCount != 0 ) { - normalizedTimeSkeleton.append(LOW_V); + if ( vCount <= 3 ) { + normalizedTimeSkeleton.append(LOW_V); + } else { + for ( int32_t j = 0; j < vCount && j < MAX_v_COUNT; ++j ) { + normalizedTimeSkeleton.append(LOW_V); + } + } + } + if ( OCount != 0 ) { + if ( OCount <= 3 ) { + normalizedTimeSkeleton.append(CAP_O); + } else { + for ( int32_t j = 0; j < OCount && j < MAX_O_COUNT; ++j ) { + normalizedTimeSkeleton.append(CAP_O); + } + } } } /** * Generate date or time interval pattern from resource, * and set them into the interval pattern locale to this formatter. * @@ -1732,18 +1758,23 @@ DateIntervalFormat::adjustFieldWidth(con findReplaceInPattern(adjustedPtn, UnicodeString(u"a\u202F",-1), UnicodeString()); findReplaceInPattern(adjustedPtn, UnicodeString(LOW_A), UnicodeString()); // adjust interior double spaces, remove exterior whitespace findReplaceInPattern(adjustedPtn, UnicodeString(" "), UnicodeString(" ")); adjustedPtn.trim(); } if ( differenceInfo == 2 ) { if (inputSkeleton.indexOf(LOW_Z) != -1) { + bestMatchSkeletonFieldWidth[(int)(LOW_Z - PATTERN_CHAR_BASE)] = bestMatchSkeletonFieldWidth[(int)(LOW_V - PATTERN_CHAR_BASE)]; findReplaceInPattern(adjustedPtn, UnicodeString(LOW_V), UnicodeString(LOW_Z)); } + if (inputSkeleton.indexOf(CAP_O) != -1) { + bestMatchSkeletonFieldWidth[(int)(CAP_O - PATTERN_CHAR_BASE)] = bestMatchSkeletonFieldWidth[(int)(LOW_V - PATTERN_CHAR_BASE)]; + findReplaceInPattern(adjustedPtn, UnicodeString(LOW_V), UnicodeString(CAP_O)); + } if (inputSkeleton.indexOf(CAP_K) != -1) { findReplaceInPattern(adjustedPtn, UnicodeString(LOW_H), UnicodeString(CAP_K)); } if (inputSkeleton.indexOf(LOW_K) != -1) { findReplaceInPattern(adjustedPtn, UnicodeString(CAP_H), UnicodeString(LOW_K)); } if (inputSkeleton.indexOf(LOW_B) != -1) { findReplaceInPattern(adjustedPtn, UnicodeString(LOW_A), UnicodeString(LOW_B)); diff --git a/intl/icu/source/i18n/dtitvinf.cpp b/intl/icu/source/i18n/dtitvinf.cpp --- a/intl/icu/source/i18n/dtitvinf.cpp +++ b/intl/icu/source/i18n/dtitvinf.cpp @@ -582,19 +582,20 @@ DateIntervalInfo::getBestSkeleton(const // hack for certain alternate characters // resource bundles only have time skeletons containing 'v', 'h', and 'H' // but not time skeletons containing 'z', 'K', or 'k' // the skeleton may also include 'a' or 'b', which never occur in the resource bundles, so strip them out too UBool replacedAlternateChars = false; const UnicodeString* inputSkeleton = &skeleton; UnicodeString copySkeleton; - if ( skeleton.indexOf(LOW_Z) != -1 || skeleton.indexOf(LOW_K) != -1 || skeleton.indexOf(CAP_K) != -1 || skeleton.indexOf(LOW_A) != -1 || skeleton.indexOf(LOW_B) != -1 ) { + if ( skeleton.indexOf(LOW_Z) != -1 || skeleton.indexOf(CAP_O) != -1 || skeleton.indexOf(LOW_K) != -1 || skeleton.indexOf(CAP_K) != -1 || skeleton.indexOf(LOW_A) != -1 || skeleton.indexOf(LOW_B) != -1 ) { copySkeleton = skeleton; copySkeleton.findAndReplace(UnicodeString(LOW_Z), UnicodeString(LOW_V)); + copySkeleton.findAndReplace(UnicodeString(CAP_O), UnicodeString(LOW_V)); copySkeleton.findAndReplace(UnicodeString(LOW_K), UnicodeString(CAP_H)); copySkeleton.findAndReplace(UnicodeString(CAP_K), UnicodeString(LOW_H)); copySkeleton.findAndReplace(UnicodeString(LOW_A), UnicodeString()); copySkeleton.findAndReplace(UnicodeString(LOW_B), UnicodeString()); inputSkeleton = ©Skeleton; replacedAlternateChars = true; }