From 3076cb2149709935df2d8caa31825de80e61452c Mon Sep 17 00:00:00 2001 From: Peter Edberg Date: Wed, 4 Mar 2015 05:43:28 +0000 Subject: [PATCH] ICU-11510 C: Support narrow AM/PM "aaaaa" for date format and parse X-SVN-Rev: 37124 --- icu4c/source/i18n/dtfmtsym.cpp | 11 ++++++++- icu4c/source/i18n/smpdtfmt.cpp | 30 +++++++++++++++++++++---- icu4c/source/i18n/unicode/dtfmtsym.h | 6 +++++ icu4c/source/test/intltest/dtfmttst.cpp | 20 +++++++++++++++++ 4 files changed, 62 insertions(+), 5 deletions(-) diff --git a/icu4c/source/i18n/dtfmtsym.cpp b/icu4c/source/i18n/dtfmtsym.cpp index e03384e3a9d..3f7f3663f19 100644 --- a/icu4c/source/i18n/dtfmtsym.cpp +++ b/icu4c/source/i18n/dtfmtsym.cpp @@ -1,6 +1,6 @@ /* ******************************************************************************* -* Copyright (C) 1997-2014, International Business Machines Corporation and * +* Copyright (C) 1997-2015, International Business Machines Corporation and * * others. All Rights Reserved. * ******************************************************************************* * @@ -202,6 +202,7 @@ static const char gNamesFormatTag[]="format"; static const char gNamesStandaloneTag[]="stand-alone"; static const char gNamesNumericTag[]="numeric"; static const char gAmPmMarkersTag[]="AmPmMarkers"; +static const char gAmPmMarkersNarrowTag[]="AmPmMarkersNarrow"; static const char gQuartersTag[]="quarters"; static const char gNumberElementsTag[]="NumberElements"; static const char gSymbolsTag[]="symbols"; @@ -368,6 +369,7 @@ DateFormatSymbols::copyData(const DateFormatSymbols& other) { assignArray(fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, other.fStandaloneShorterWeekdays, other.fStandaloneShorterWeekdaysCount); assignArray(fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, other.fStandaloneNarrowWeekdays, other.fStandaloneNarrowWeekdaysCount); assignArray(fAmPms, fAmPmsCount, other.fAmPms, other.fAmPmsCount); + assignArray(fNarrowAmPms, fNarrowAmPmsCount, other.fNarrowAmPms, other.fNarrowAmPmsCount ); fTimeSeparator.fastCopyFrom(other.fTimeSeparator); // fastCopyFrom() - see assignArray comments assignArray(fQuarters, fQuartersCount, other.fQuarters, other.fQuartersCount); assignArray(fShortQuarters, fShortQuartersCount, other.fShortQuarters, other.fShortQuartersCount); @@ -448,6 +450,7 @@ void DateFormatSymbols::dispose() if (fStandaloneShorterWeekdays) delete[] fStandaloneShorterWeekdays; if (fStandaloneNarrowWeekdays) delete[] fStandaloneNarrowWeekdays; if (fAmPms) delete[] fAmPms; + if (fNarrowAmPms) delete[] fNarrowAmPms; if (fQuarters) delete[] fQuarters; if (fShortQuarters) delete[] fShortQuarters; if (fStandaloneQuarters) delete[] fStandaloneQuarters; @@ -519,6 +522,7 @@ DateFormatSymbols::operator==(const DateFormatSymbols& other) const fStandaloneShorterWeekdaysCount == other.fStandaloneShorterWeekdaysCount && fStandaloneNarrowWeekdaysCount == other.fStandaloneNarrowWeekdaysCount && fAmPmsCount == other.fAmPmsCount && + fNarrowAmPmsCount == other.fNarrowAmPmsCount && fQuartersCount == other.fQuartersCount && fShortQuartersCount == other.fShortQuartersCount && fStandaloneQuartersCount == other.fStandaloneQuartersCount && @@ -547,6 +551,7 @@ DateFormatSymbols::operator==(const DateFormatSymbols& other) const arrayCompare(fStandaloneShorterWeekdays, other.fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount) && arrayCompare(fStandaloneNarrowWeekdays, other.fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount) && arrayCompare(fAmPms, other.fAmPms, fAmPmsCount) && + arrayCompare(fNarrowAmPms, other.fNarrowAmPms, fNarrowAmPmsCount) && fTimeSeparator == other.fTimeSeparator && arrayCompare(fQuarters, other.fQuarters, fQuartersCount) && arrayCompare(fShortQuarters, other.fShortQuarters, fShortQuartersCount) && @@ -1501,6 +1506,8 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError fStandaloneNarrowWeekdaysCount=0; fAmPms = NULL; fAmPmsCount=0; + fNarrowAmPms = NULL; + fNarrowAmPmsCount=0; fTimeSeparator.setToBogus(); fQuarters = NULL; fQuartersCount = 0; @@ -1716,6 +1723,7 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError initField(&fStandaloneShorterWeekdays, fStandaloneShorterWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status); initField(&fStandaloneNarrowWeekdays, fStandaloneNarrowWeekdaysCount, (const UChar *)gLastResortDayNames, kDayNum, kDayLen, status); initField(&fAmPms, fAmPmsCount, (const UChar *)gLastResortAmPmMarkers, kAmPmNum, kAmPmLen, status); + initField(&fNarrowAmPms, fNarrowAmPmsCount, (const UChar *)gLastResortAmPmMarkers, kAmPmNum, kAmPmLen, status); initField(&fQuarters, fQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status); initField(&fShortQuarters, fShortQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status); initField(&fStandaloneQuarters, fStandaloneQuartersCount, (const UChar *)gLastResortQuarters, kQuarterNum, kQuarterLen, status); @@ -1768,6 +1776,7 @@ DateFormatSymbols::initializeData(const Locale& locale, const char *type, UError } } initField(&fAmPms, fAmPmsCount, calData.getByKey(gAmPmMarkersTag, status), status); + initField(&fNarrowAmPms, fNarrowAmPmsCount, calData.getByKey(gAmPmMarkersNarrowTag, status), status); initField(&fQuarters, fQuartersCount, calData.getByKey2(gQuartersTag, gNamesWideTag, status), status); initField(&fShortQuarters, fShortQuartersCount, calData.getByKey2(gQuartersTag, gNamesAbbrTag, status), status); diff --git a/icu4c/source/i18n/smpdtfmt.cpp b/icu4c/source/i18n/smpdtfmt.cpp index 9a7c107aeeb..2b309f208a3 100644 --- a/icu4c/source/i18n/smpdtfmt.cpp +++ b/icu4c/source/i18n/smpdtfmt.cpp @@ -1617,10 +1617,15 @@ SimpleDateFormat::subFormat(UnicodeString &appendTo, } break; - // for and "a" symbol, write out the whole AM/PM string + // for "a" symbol, write out the whole AM/PM string case UDAT_AM_PM_FIELD: - _appendSymbol(appendTo, value, fSymbols->fAmPms, - fSymbols->fAmPmsCount); + if (count < 5) { + _appendSymbol(appendTo, value, fSymbols->fAmPms, + fSymbols->fAmPmsCount); + } else { + _appendSymbol(appendTo, value, fSymbols->fNarrowAmPms, + fSymbols->fNarrowAmPmsCount); + } break; // for ":", write out the time separator string @@ -3022,7 +3027,24 @@ int32_t SimpleDateFormat::subParse(const UnicodeString& text, int32_t& start, UC break; case UDAT_AM_PM_FIELD: - return matchString(text, start, UCAL_AM_PM, fSymbols->fAmPms, fSymbols->fAmPmsCount, NULL, cal); + { + // optionally try both wide/abbrev and narrow forms + int32_t newStart = 0; + // try wide/abbrev + if( getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status) || count < 5 ) { + if ((newStart = matchString(text, start, UCAL_AM_PM, fSymbols->fAmPms, fSymbols->fAmPmsCount, NULL, cal)) > 0) { + return newStart; + } + } + // try narrow + if( getBooleanAttribute(UDAT_PARSE_MULTIPLE_PATTERNS_FOR_MATCH, status) || count >= 5 ) { + if ((newStart = matchString(text, start, UCAL_AM_PM, fSymbols->fNarrowAmPms, fSymbols->fNarrowAmPmsCount, NULL, cal)) > 0) { + return newStart; + } + } + // no matches for given options + return -start; + } case UDAT_HOUR1_FIELD: // [We computed 'value' above.] diff --git a/icu4c/source/i18n/unicode/dtfmtsym.h b/icu4c/source/i18n/unicode/dtfmtsym.h index dd920d39aa3..a6e90a4c188 100644 --- a/icu4c/source/i18n/unicode/dtfmtsym.h +++ b/icu4c/source/i18n/unicode/dtfmtsym.h @@ -740,6 +740,12 @@ private: UnicodeString* fAmPms; int32_t fAmPmsCount; + /** + * Narrow Ampm strings. For example: "a" and "p". + */ + UnicodeString* fNarrowAmPms; + int32_t fNarrowAmPmsCount; + /** * Time separator string. For example: ":". */ diff --git a/icu4c/source/test/intltest/dtfmttst.cpp b/icu4c/source/test/intltest/dtfmttst.cpp index 1b2ce266c14..ad96b5d3b5c 100644 --- a/icu4c/source/test/intltest/dtfmttst.cpp +++ b/icu4c/source/test/intltest/dtfmttst.cpp @@ -1752,6 +1752,11 @@ void DateFormatTest::TestNarrowNames() "ccccc", "1970 01 01 0:00:00", "T", "ccccc", "1970 01 02 0:00:00", "F", "ccccc", "1970 01 03 0:00:00", "S", + + "h:mm a", "2015 01 01 10:00:00", "10:00 AM", + "h:mm a", "2015 01 01 22:00:00", "10:00 PM", + "h:mm aaaaa", "2015 01 01 10:00:00", "10:00 a", + "h:mm aaaaa", "2015 01 01 22:00:00", "10:00 p", }; const char *CS_DATA[] = { @@ -1801,10 +1806,25 @@ void DateFormatTest::TestNarrowNames() "ccccc", "1970 01 01 0:00:00", "\\u010C", "ccccc", "1970 01 02 0:00:00", "P", "ccccc", "1970 01 03 0:00:00", "S", + + "h:mm a", "2015 01 01 10:00:00", "10:00 AM", + "h:mm a", "2015 01 01 22:00:00", "10:00 PM", + "h:mm aaaaa", "2015 01 01 10:00:00", "10:00 AM", + "h:mm aaaaa", "2015 01 01 22:00:00", "10:00 PM", + }; + + const char *CA_DATA[] = { + "yyyy MM dd HH:mm:ss", + + "h:mm a", "2015 01 01 10:00:00", "10:00 a. m.", + "h:mm a", "2015 01 01 22:00:00", "10:00 p. m.", + "h:mm aaaaa", "2015 01 01 10:00:00", "10:00 a.m.", + "h:mm aaaaa", "2015 01 01 22:00:00", "10:00 p.m.", }; expectFormat(EN_DATA, ARRAY_SIZE(EN_DATA), Locale("en", "", "")); expectFormat(CS_DATA, ARRAY_SIZE(CS_DATA), Locale("cs", "", "")); + expectFormat(CA_DATA, ARRAY_SIZE(CA_DATA), Locale("ca", "", "")); } void DateFormatTest::TestEras() -- 2.40.0