From ebea161b11623189a00cb1a66d5110be38f72438 Mon Sep 17 00:00:00 2001 From: Peter Edberg Date: Tue, 10 Sep 2013 07:51:38 +0000 Subject: [PATCH] ICU-10065 In DateTimePatternGenerator, add support for pattern chars K,O,X,x, adjust support for V X-SVN-Rev: 34256 --- icu4c/source/i18n/dtptngen.cpp | 18 +++- icu4c/source/i18n/dtptngen_impl.h | 4 +- icu4c/source/test/intltest/dtptngts.cpp | 136 ++++++++++++++++++++++++ icu4c/source/test/intltest/dtptngts.h | 3 +- 4 files changed, 155 insertions(+), 6 deletions(-) diff --git a/icu4c/source/i18n/dtptngen.cpp b/icu4c/source/i18n/dtptngen.cpp index ddb553272d1..023ad7e1bbd 100644 --- a/icu4c/source/i18n/dtptngen.cpp +++ b/icu4c/source/i18n/dtptngen.cpp @@ -181,8 +181,9 @@ static const dtTypeElem dtTypes[] = { {LOW_G, UDATPG_DAY_FIELD, DT_NUMERIC + 3*DT_DELTA, 1, 20}, // really internal use, so we don't care {LOW_A, UDATPG_DAYPERIOD_FIELD, DT_SHORT, 1, 0}, {CAP_H, UDATPG_HOUR_FIELD, DT_NUMERIC + 10*DT_DELTA, 1, 2}, // 24 hour - {LOW_K, UDATPG_HOUR_FIELD, DT_NUMERIC + 11*DT_DELTA, 1, 2}, + {LOW_K, UDATPG_HOUR_FIELD, DT_NUMERIC + 11*DT_DELTA, 1, 2}, // 24 hour {LOW_H, UDATPG_HOUR_FIELD, DT_NUMERIC, 1, 2}, // 12 hour + {CAP_K, UDATPG_HOUR_FIELD, DT_NUMERIC + DT_DELTA, 1, 2}, // 12 hour {LOW_K, UDATPG_HOUR_FIELD, DT_NUMERIC + DT_DELTA, 1, 2}, {LOW_M, UDATPG_MINUTE_FIELD, DT_NUMERIC, 1, 2}, {LOW_S, UDATPG_SECOND_FIELD, DT_NUMERIC, 1, 2}, @@ -192,10 +193,19 @@ static const dtTypeElem dtTypes[] = { {LOW_V, UDATPG_ZONE_FIELD, DT_LONG - 2*DT_DELTA, 4, 0}, {LOW_Z, UDATPG_ZONE_FIELD, DT_SHORT, 1, 3}, {LOW_Z, UDATPG_ZONE_FIELD, DT_LONG, 4, 0}, - {CAP_Z, UDATPG_ZONE_FIELD, DT_SHORT - DT_DELTA, 1, 3}, + {CAP_Z, UDATPG_ZONE_FIELD, DT_NARROW - DT_DELTA, 1, 3}, {CAP_Z, UDATPG_ZONE_FIELD, DT_LONG - DT_DELTA, 4, 0}, - {CAP_V, UDATPG_ZONE_FIELD, DT_SHORT - DT_DELTA, 1, 3}, - {CAP_V, UDATPG_ZONE_FIELD, DT_LONG - DT_DELTA, 4, 0}, + {CAP_Z, UDATPG_ZONE_FIELD, DT_SHORT - DT_DELTA, 5, 0}, + {CAP_O, UDATPG_ZONE_FIELD, DT_SHORT - DT_DELTA, 1, 0}, + {CAP_O, UDATPG_ZONE_FIELD, DT_LONG - DT_DELTA, 4, 0}, + {CAP_V, UDATPG_ZONE_FIELD, DT_SHORT - DT_DELTA, 1, 0}, + {CAP_V, UDATPG_ZONE_FIELD, DT_LONG - DT_DELTA, 2, 0}, + {CAP_X, UDATPG_ZONE_FIELD, DT_NARROW - DT_DELTA, 1, 0}, + {CAP_X, UDATPG_ZONE_FIELD, DT_SHORT - DT_DELTA, 2, 0}, + {CAP_X, UDATPG_ZONE_FIELD, DT_LONG - DT_DELTA, 4, 0}, + {LOW_X, UDATPG_ZONE_FIELD, DT_NARROW - DT_DELTA, 1, 0}, + {LOW_X, UDATPG_ZONE_FIELD, DT_SHORT - DT_DELTA, 2, 0}, + {LOW_X, UDATPG_ZONE_FIELD, DT_LONG - DT_DELTA, 4, 0}, {0, UDATPG_FIELD_COUNT, 0, 0, 0} , // last row of dtTypes[] }; diff --git a/icu4c/source/i18n/dtptngen_impl.h b/icu4c/source/i18n/dtptngen_impl.h index f76f003d490..7f29bab226a 100644 --- a/icu4c/source/i18n/dtptngen_impl.h +++ b/icu4c/source/i18n/dtptngen_impl.h @@ -1,6 +1,6 @@ /* ******************************************************************************* -* Copyright (C) 2007-2012, International Business Machines Corporation and +* Copyright (C) 2007-2013, International Business Machines Corporation and * others. All Rights Reserved. * ******************************************************************************* * @@ -54,6 +54,7 @@ #define CAP_U ((UChar)0x0055) #define CAP_V ((UChar)0x0056) #define CAP_W ((UChar)0x0057) +#define CAP_X ((UChar)0x0058) #define CAP_Y ((UChar)0x0059) #define CAP_Z ((UChar)0x005A) #define LOWLINE ((UChar)0x005F) @@ -79,6 +80,7 @@ #define LOW_U ((UChar)0x0075) #define LOW_V ((UChar)0x0076) #define LOW_W ((UChar)0x0077) +#define LOW_X ((UChar)0x0078) #define LOW_Y ((UChar)0x0079) #define LOW_Z ((UChar)0x007A) #define DT_SHORT -0x102 diff --git a/icu4c/source/test/intltest/dtptngts.cpp b/icu4c/source/test/intltest/dtptngts.cpp index f5e2e1d7a25..1e2cecf0e93 100644 --- a/icu4c/source/test/intltest/dtptngts.cpp +++ b/icu4c/source/test/intltest/dtptngts.cpp @@ -29,6 +29,7 @@ void IntlTestDateTimePatternGeneratorAPI::runIndexedTest( int32_t index, UBool e switch (index) { TESTCASE(0, testAPI); TESTCASE(1, testOptions); + TESTCASE(2, testAllFieldPatterns); default: name = ""; break; } } @@ -890,4 +891,139 @@ void IntlTestDateTimePatternGeneratorAPI::testOptions(/*char *par*/) } } +/** + * Test that DTPG can handle all valid pattern character / length combinations + * + */ +#define FIELD_LENGTHS_COUNT 6 +#define FIELD_LENGTH_MAX 8 +#define MUST_INCLUDE_COUNT 5 + +typedef struct AllFieldsTestItem { + char patternChar; + int8_t fieldLengths[FIELD_LENGTHS_COUNT+1]; // up to FIELD_LENGTHS_COUNT lengths to try + // (length <=FIELD_LENGTH_MAX) plus 0 terminator + char mustIncludeOneOf[MUST_INCLUDE_COUNT+1];// resulting pattern must include at least one of + // these as a pattern char (0-terminated list) +} AllFieldsTestItem; + +void IntlTestDateTimePatternGeneratorAPI::testAllFieldPatterns(/*char *par*/) +{ + const char * localeNames[] = { + "root", + "root@calendar=japanese", + "root@calendar=chinese", + "en", + "en@calendar=japanese", + "en@calendar=chinese", + NULL // terminator + }; + AllFieldsTestItem testData[] = { + //pat fieldLengths generated pattern must + //chr to test include one of these + { 'G', {1,2,3,4,5,0}, "G" }, // era + // year + { 'y', {1,2,3,4,0}, "yU" }, // year + { 'Y', {1,2,3,4,0}, "Y" }, // year for week of year + { 'u', {1,2,3,4,5,0}, "yuU" }, // extended year + { 'U', {1,2,3,4,5,0}, "yU" }, // cyclic year name + // quarter + { 'Q', {1,2,3,4,0}, "Qq" }, // x + { 'q', {1,2,3,4,0}, "Qq" }, // standalone + // month + { 'M', {1,2,3,4,5,0}, "ML" }, // x + { 'L', {1,2,3,4,5,0}, "ML" }, // standalone + // week + { 'w', {1,2,0}, "w" }, // week of year + { 'W', {1,0}, "W" }, // week of month + // day + { 'd', {1,2,0}, "d" }, // day of month + { 'D', {1,2,3,0}, "D" }, // day of year + { 'F', {1,0}, "F" }, // day of week in month + { 'g', {7,0}, "g" }, // modified julian day + // weekday + { 'E', {1,2,3,4,5,6}, "Eec" }, // day of week + { 'e', {1,2,3,4,5,6}, "Eec" }, // local day of week + { 'c', {1,2,3,4,5,6}, "Eec" }, // standalone local day of week + // day period + // { 'a', {1,0}, "a" }, // am or pm // not clear this one is supposed to work (it doesn't) + // hour + { 'h', {1,2,0}, "hK" }, // 12 (1-12) + { 'H', {1,2,0}, "Hk" }, // 24 (0-23) + { 'K', {1,2,0}, "hK" }, // 12 (0-11) + { 'k', {1,2,0}, "Hk" }, // 24 (1-24) + { 'j', {1,2,0}, "hHKk" }, // locale default + // minute + { 'm', {1,2,0}, "m" }, // x + // second & fractions + { 's', {1,2,0}, "s" }, // x + { 'S', {1,2,3,4,0}, "S" }, // fractional second + { 'A', {8,0}, "A" }, // milliseconds in day + // zone + { 'z', {1,2,3,4,0}, "z" }, // x + { 'Z', {1,2,3,4,5,0}, "Z" }, // x + { 'O', {1,4,0}, "O" }, // x + { 'v', {1,4,0}, "v" }, // x + { 'V', {1,2,3,4,0}, "V" }, // x + { 'X', {1,2,3,4,5,0}, "X" }, // x + { 'x', {1,2,3,4,5,0}, "x" }, // x + }; + + const char ** localeNamesPtr = localeNames; + const char * localeName; + while ( (localeName = *localeNamesPtr++) != NULL) { + UErrorCode status = U_ZERO_ERROR; + Locale locale = Locale::createFromName(localeName); + DateTimePatternGenerator * dtpg = DateTimePatternGenerator::createInstance(locale, status); + if (U_SUCCESS(status)) { + const AllFieldsTestItem * testDataPtr = testData; + int itemCount = sizeof(testData) / sizeof(testData[0]); + for (; itemCount-- > 0; ++testDataPtr) { + char skelBuf[FIELD_LENGTH_MAX]; + int32_t chrIndx, lenIndx; + for (chrIndx = 0; chrIndx < FIELD_LENGTH_MAX; chrIndx++) { + skelBuf[chrIndx] = testDataPtr->patternChar; + } + for (lenIndx = 0; lenIndx < FIELD_LENGTHS_COUNT; lenIndx++) { + int32_t skelLen = testDataPtr->fieldLengths[lenIndx]; + if (skelLen <= 0) { + break; + } + UnicodeString skeleton(skelBuf, skelLen, US_INV); + UnicodeString pattern = dtpg->getBestPattern(skeleton, status); + if (U_SUCCESS(status)) { + // test that resulting pattern has at least one char in mustIncludeOneOf + UnicodeString mustIncludeOneOf(testDataPtr->mustIncludeOneOf, -1, US_INV); + int32_t patIndx, patLen = pattern.length(); + UBool inQuoted = FALSE; + for (patIndx = 0; patIndx < patLen; patIndx++) { + UChar c = pattern.charAt(patIndx); + if (c == 0x27) { + inQuoted = !inQuoted; + } else if (!inQuoted && c <= 0x007A &&c >= 0x0041) { + if (mustIncludeOneOf.indexOf(c) >= 0) { + break; + } + } + } + if (patIndx >= patLen) { + errln(UnicodeString("DateTimePatternGenerator getBestPattern for locale ") + + UnicodeString(locale.getName(),-1,US_INV) + + ", skeleton " + skeleton + + ", produces pattern without required chars: " + pattern); + } + + } else { + errln("DateTimePatternGenerator getBestPattern for locale %s, skelChar %c skelLength %d fails: %s", + locale.getName(), testDataPtr->patternChar, skelLen, u_errorName(status)); + } + } + } + delete dtpg; + } else { + dataerrln("Create DateTimePatternGenerator instance for locale(%s) fails: %s", + locale.getName(), u_errorName(status)); + } + } +} #endif /* #if !UCONFIG_NO_FORMATTING */ diff --git a/icu4c/source/test/intltest/dtptngts.h b/icu4c/source/test/intltest/dtptngts.h index e81e2c1edf3..40c24d7869f 100644 --- a/icu4c/source/test/intltest/dtptngts.h +++ b/icu4c/source/test/intltest/dtptngts.h @@ -1,6 +1,6 @@ /******************************************************************** * COPYRIGHT: - * Copyright (c) 1997-2001,2009, International Business Machines Corporation and + * Copyright (c) 1997-2001,2009,2013, International Business Machines Corporation and * others. All Rights Reserved. ********************************************************************/ @@ -25,6 +25,7 @@ private: **/ void testAPI(/* char* par */); void testOptions(/* char* par */); + void testAllFieldPatterns(/* char* par */); }; #endif /* #if !UCONFIG_NO_FORMATTING */ -- 2.40.0