bug-1856290-ICU-20548-dateinterval-timezone.diff (6638B)
1 # Handle 'O' time zone skeleton in DateIntervalFormat. 2 # Keep time zone skeleton field widths in DateIntervalFormat. 3 # 4 # ICU bug: https://unicode-org.atlassian.net/browse/ICU-20548 5 6 diff --git a/intl/icu/source/i18n/dtitv_impl.h b/intl/icu/source/i18n/dtitv_impl.h 7 --- a/intl/icu/source/i18n/dtitv_impl.h 8 +++ b/intl/icu/source/i18n/dtitv_impl.h 9 @@ -84,16 +84,19 @@ 10 #define CAP_W ((char16_t)0x0057) 11 #define CAP_Y ((char16_t)0x0059) 12 #define CAP_Z ((char16_t)0x005A) 13 14 //#define MINIMUM_SUPPORTED_CALENDAR_FIELD UCAL_MINUTE 15 16 #define MAX_E_COUNT 5 17 #define MAX_M_COUNT 5 18 +#define MAX_z_COUNT 4 19 +#define MAX_v_COUNT 4 20 +#define MAX_O_COUNT 4 21 //#define MAX_INTERVAL_INDEX 4 22 #define MAX_POSITIVE_INT 56632 23 24 25 #endif /* #if !UCONFIG_NO_FORMATTING */ 26 27 #endif 28 //eof 29 diff --git a/intl/icu/source/i18n/dtitvfmt.cpp b/intl/icu/source/i18n/dtitvfmt.cpp 30 --- a/intl/icu/source/i18n/dtitvfmt.cpp 31 +++ b/intl/icu/source/i18n/dtitvfmt.cpp 32 @@ -1061,16 +1061,17 @@ DateIntervalFormat::getDateTimeSkeleton( 33 // timeSkeleton follows the sequence of hm*[v|z]? 34 int32_t ECount = 0; 35 int32_t dCount = 0; 36 int32_t MCount = 0; 37 int32_t yCount = 0; 38 int32_t mCount = 0; 39 int32_t vCount = 0; 40 int32_t zCount = 0; 41 + int32_t OCount = 0; 42 char16_t hourChar = u'\0'; 43 int32_t i; 44 45 for (i = 0; i < skeleton.length(); ++i) { 46 char16_t ch = skeleton[i]; 47 switch ( ch ) { 48 case CAP_E: 49 dateSkeleton.append(ch); 50 @@ -1123,16 +1124,20 @@ DateIntervalFormat::getDateTimeSkeleton( 51 case LOW_Z: 52 ++zCount; 53 timeSkeleton.append(ch); 54 break; 55 case LOW_V: 56 ++vCount; 57 timeSkeleton.append(ch); 58 break; 59 + case CAP_O: 60 + ++OCount; 61 + timeSkeleton.append(ch); 62 + break; 63 case LOW_A: 64 case CAP_V: 65 case CAP_Z: 66 case LOW_J: 67 case LOW_S: 68 case CAP_S: 69 case CAP_A: 70 case LOW_B: 71 @@ -1174,20 +1179,41 @@ DateIntervalFormat::getDateTimeSkeleton( 72 /* generate normalized form for time */ 73 if ( hourChar != u'\0' ) { 74 normalizedTimeSkeleton.append(hourChar); 75 } 76 if ( mCount != 0 ) { 77 normalizedTimeSkeleton.append(LOW_M); 78 } 79 if ( zCount != 0 ) { 80 - normalizedTimeSkeleton.append(LOW_Z); 81 + if ( zCount <= 3 ) { 82 + normalizedTimeSkeleton.append(LOW_Z); 83 + } else { 84 + for ( int32_t j = 0; j < zCount && j < MAX_z_COUNT; ++j ) { 85 + normalizedTimeSkeleton.append(LOW_Z); 86 + } 87 + } 88 } 89 if ( vCount != 0 ) { 90 - normalizedTimeSkeleton.append(LOW_V); 91 + if ( vCount <= 3 ) { 92 + normalizedTimeSkeleton.append(LOW_V); 93 + } else { 94 + for ( int32_t j = 0; j < vCount && j < MAX_v_COUNT; ++j ) { 95 + normalizedTimeSkeleton.append(LOW_V); 96 + } 97 + } 98 + } 99 + if ( OCount != 0 ) { 100 + if ( OCount <= 3 ) { 101 + normalizedTimeSkeleton.append(CAP_O); 102 + } else { 103 + for ( int32_t j = 0; j < OCount && j < MAX_O_COUNT; ++j ) { 104 + normalizedTimeSkeleton.append(CAP_O); 105 + } 106 + } 107 } 108 } 109 110 111 /** 112 * Generate date or time interval pattern from resource, 113 * and set them into the interval pattern locale to this formatter. 114 * 115 @@ -1732,18 +1758,23 @@ DateIntervalFormat::adjustFieldWidth(con 116 findReplaceInPattern(adjustedPtn, UnicodeString(u"a\u202F",-1), UnicodeString()); 117 findReplaceInPattern(adjustedPtn, UnicodeString(LOW_A), UnicodeString()); 118 // adjust interior double spaces, remove exterior whitespace 119 findReplaceInPattern(adjustedPtn, UnicodeString(" "), UnicodeString(" ")); 120 adjustedPtn.trim(); 121 } 122 if ( differenceInfo == 2 ) { 123 if (inputSkeleton.indexOf(LOW_Z) != -1) { 124 + bestMatchSkeletonFieldWidth[(int)(LOW_Z - PATTERN_CHAR_BASE)] = bestMatchSkeletonFieldWidth[(int)(LOW_V - PATTERN_CHAR_BASE)]; 125 findReplaceInPattern(adjustedPtn, UnicodeString(LOW_V), UnicodeString(LOW_Z)); 126 } 127 + if (inputSkeleton.indexOf(CAP_O) != -1) { 128 + bestMatchSkeletonFieldWidth[(int)(CAP_O - PATTERN_CHAR_BASE)] = bestMatchSkeletonFieldWidth[(int)(LOW_V - PATTERN_CHAR_BASE)]; 129 + findReplaceInPattern(adjustedPtn, UnicodeString(LOW_V), UnicodeString(CAP_O)); 130 + } 131 if (inputSkeleton.indexOf(CAP_K) != -1) { 132 findReplaceInPattern(adjustedPtn, UnicodeString(LOW_H), UnicodeString(CAP_K)); 133 } 134 if (inputSkeleton.indexOf(LOW_K) != -1) { 135 findReplaceInPattern(adjustedPtn, UnicodeString(CAP_H), UnicodeString(LOW_K)); 136 } 137 if (inputSkeleton.indexOf(LOW_B) != -1) { 138 findReplaceInPattern(adjustedPtn, UnicodeString(LOW_A), UnicodeString(LOW_B)); 139 diff --git a/intl/icu/source/i18n/dtitvinf.cpp b/intl/icu/source/i18n/dtitvinf.cpp 140 --- a/intl/icu/source/i18n/dtitvinf.cpp 141 +++ b/intl/icu/source/i18n/dtitvinf.cpp 142 @@ -582,19 +582,20 @@ DateIntervalInfo::getBestSkeleton(const 143 144 // hack for certain alternate characters 145 // resource bundles only have time skeletons containing 'v', 'h', and 'H' 146 // but not time skeletons containing 'z', 'K', or 'k' 147 // the skeleton may also include 'a' or 'b', which never occur in the resource bundles, so strip them out too 148 UBool replacedAlternateChars = false; 149 const UnicodeString* inputSkeleton = &skeleton; 150 UnicodeString copySkeleton; 151 - 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 ) { 152 + 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 ) { 153 copySkeleton = skeleton; 154 copySkeleton.findAndReplace(UnicodeString(LOW_Z), UnicodeString(LOW_V)); 155 + copySkeleton.findAndReplace(UnicodeString(CAP_O), UnicodeString(LOW_V)); 156 copySkeleton.findAndReplace(UnicodeString(LOW_K), UnicodeString(CAP_H)); 157 copySkeleton.findAndReplace(UnicodeString(CAP_K), UnicodeString(LOW_H)); 158 copySkeleton.findAndReplace(UnicodeString(LOW_A), UnicodeString()); 159 copySkeleton.findAndReplace(UnicodeString(LOW_B), UnicodeString()); 160 inputSkeleton = ©Skeleton; 161 replacedAlternateChars = true; 162 }