From 3d1c1bb07aa3414de08256f90b36535ccd2d2ab8 Mon Sep 17 00:00:00 2001 From: Travis Keep Date: Thu, 22 May 2014 22:46:53 +0000 Subject: [PATCH] ICU-10884 Add abbreviated relative date format support. X-SVN-Rev: 35744 --- .gitattributes | 2 + icu4c/source/data/locales/en.txt | 385 +++++++++++- icu4c/source/data/locales/root.txt | 48 +- icu4c/source/i18n/Makefile.in | 2 +- icu4c/source/i18n/i18n.vcxproj | 2 + icu4c/source/i18n/i18n.vcxproj.filters | 6 + icu4c/source/i18n/reldatefmt.cpp | 421 +++++++++++--- icu4c/source/i18n/sharedbreakiterator.cpp | 21 + icu4c/source/i18n/sharedbreakiterator.h | 43 ++ icu4c/source/i18n/unicode/reldatefmt.h | 59 +- icu4c/source/test/intltest/reldatefmttest.cpp | 500 +++++++++++++++- icu4c/source/test/testdata/structLocale.txt | 548 ++++++++++++++++++ 12 files changed, 1941 insertions(+), 96 deletions(-) create mode 100644 icu4c/source/i18n/sharedbreakiterator.cpp create mode 100644 icu4c/source/i18n/sharedbreakiterator.h diff --git a/.gitattributes b/.gitattributes index e990c50435..a740559877 100644 --- a/.gitattributes +++ b/.gitattributes @@ -75,6 +75,8 @@ icu4c/source/extra/uconv/uconv.vcxproj.filters -text icu4c/source/i18n/i18n.vcxproj -text icu4c/source/i18n/i18n.vcxproj.filters -text icu4c/source/i18n/scientificformathelper.cpp -text +icu4c/source/i18n/sharedbreakiterator.cpp -text +icu4c/source/i18n/sharedbreakiterator.h -text icu4c/source/i18n/unicode/scientificformathelper.h -text icu4c/source/io/io.vcxproj -text icu4c/source/io/io.vcxproj.filters -text diff --git a/icu4c/source/data/locales/en.txt b/icu4c/source/data/locales/en.txt index 6067a92b5d..ab72656b4a 100644 --- a/icu4c/source/data/locales/en.txt +++ b/icu4c/source/data/locales/en.txt @@ -6,9 +6,6 @@ // * Source File: /common/main/en.xml // * // *************************************************************************** -/** - * ICU source: /common/main/en.xml - */ en{ AuxExemplarCharacters{ "[á à ă â å ä ã ā æ ç é è ĕ ê ë ē í ì ĭ î ï ī ñ ó ò ŏ ô ö ø ō œ ú ù ŭ û ü ū ÿ" @@ -154,7 +151,7 @@ en{ } } } - Version{"2.0.98.76"} + Version{"2.1.3.5"} calendar{ buddhist{ eras{ @@ -903,6 +900,42 @@ en{ } } } + day-narrow{ + dn{"Day"} + relative{ + "-1"{"yesterday"} + "0"{"today"} + "1"{"tomorrow"} + } + relativeTime{ + future{ + one{"+{0} day"} + other{"+{0} days"} + } + past{ + one{"-{0} day"} + other{"-{0} days"} + } + } + } + day-short{ + dn{"Day"} + relative{ + "-1"{"yesterday"} + "0"{"today"} + "1"{"tomorrow"} + } + relativeTime{ + future{ + one{"in {0} day"} + other{"in {0} days"} + } + past{ + one{"{0} day ago"} + other{"{0} days ago"} + } + } + } dayperiod{ dn{"AM/PM"} } @@ -916,6 +949,20 @@ en{ "1"{"next Friday"} } } + fri-narrow{ + relative{ + "-1"{"last F"} + "0"{"this F"} + "1"{"next F"} + } + } + fri-short{ + relative{ + "-1"{"last Fri."} + "0"{"this Fri."} + "1"{"next Fri."} + } + } hour{ dn{"Hour"} relativeTime{ @@ -929,6 +976,32 @@ en{ } } } + hour-narrow{ + dn{"h"} + relativeTime{ + future{ + one{"+{0} h"} + other{"+{0} h"} + } + past{ + one{"-{0} h"} + other{"-{0} h"} + } + } + } + hour-short{ + dn{"hr."} + relativeTime{ + future{ + one{"in {0} hr."} + other{"in {0} hr."} + } + past{ + one{"{0} hr. ago"} + other{"{0} hr. ago"} + } + } + } minute{ dn{"Minute"} relativeTime{ @@ -942,6 +1015,32 @@ en{ } } } + minute-narrow{ + dn{"m"} + relativeTime{ + future{ + one{"+{0} m"} + other{"+{0} m"} + } + past{ + one{"-{0} m"} + other{"-{0} m"} + } + } + } + minute-short{ + dn{"min."} + relativeTime{ + future{ + one{"in {0} min."} + other{"in {0} min."} + } + past{ + one{"{0} min. ago"} + other{"{0} min. ago"} + } + } + } mon{ relative{ "-1"{"last Monday"} @@ -949,6 +1048,20 @@ en{ "1"{"next Monday"} } } + mon-narrow{ + relative{ + "-1"{"last M"} + "0"{"this M"} + "1"{"next M"} + } + } + mon-short{ + relative{ + "-1"{"last Mon."} + "0"{"this Mon."} + "1"{"next Mon."} + } + } month{ dn{"Month"} relative{ @@ -967,6 +1080,96 @@ en{ } } } + month-narrow{ + dn{"mo."} + relative{ + "-1"{"last mo."} + "0"{"this mo."} + "1"{"next mo."} + } + relativeTime{ + future{ + one{"+{0} mo."} + other{"+{0} mo."} + } + past{ + one{"-{0} mo."} + other{"-{0} mo."} + } + } + } + month-short{ + dn{"mo."} + relative{ + "-1"{"last mo."} + "0"{"this mo."} + "1"{"next mo."} + } + relativeTime{ + future{ + one{"in {0} mo."} + other{"in {0} mo."} + } + past{ + one{"{0} mo. ago"} + other{"{0} mo. ago"} + } + } + } + quarter{ + dn{"Quarter"} + relative{ + "-1"{"last quarter"} + "0"{"this quarter"} + "1"{"next quarter"} + } + relativeTime{ + future{ + one{"in {0} quarter"} + other{"in {0} quarters"} + } + past{ + one{"{0} quarter ago"} + other{"{0} quarters ago"} + } + } + } + quarter-narrow{ + dn{"qtr."} + relative{ + "-1"{"last qtr."} + "0"{"this qtr."} + "1"{"next qtr."} + } + relativeTime{ + future{ + one{"+{0} Q"} + other{"+{0} Q"} + } + past{ + one{"-{0} Q"} + other{"-{0} Q"} + } + } + } + quarter-short{ + dn{"qtr."} + relative{ + "-1"{"last qtr."} + "0"{"this qtr."} + "1"{"next qtr."} + } + relativeTime{ + future{ + one{"in {0} qtr."} + other{"in {0} qtrs."} + } + past{ + one{"{0} qtr. ago"} + other{"{0} qtrs. ago"} + } + } + } sat{ relative{ "-1"{"last Saturday"} @@ -974,6 +1177,20 @@ en{ "1"{"next Saturday"} } } + sat-narrow{ + relative{ + "-1"{"last Sa"} + "0"{"this Sa"} + "1"{"next Sa"} + } + } + sat-short{ + relative{ + "-1"{"last Sat."} + "0"{"this Sat."} + "1"{"next Sat."} + } + } second{ dn{"Second"} relative{ @@ -990,6 +1207,38 @@ en{ } } } + second-narrow{ + dn{"s"} + relative{ + "0"{"now"} + } + relativeTime{ + future{ + one{"+{0} s"} + other{"+{0} s"} + } + past{ + one{"-{0} s"} + other{"-{0} s"} + } + } + } + second-short{ + dn{"sec."} + relative{ + "0"{"now"} + } + relativeTime{ + future{ + one{"in {0} sec."} + other{"in {0} sec."} + } + past{ + one{"{0} sec. ago"} + other{"{0} sec. ago"} + } + } + } sun{ relative{ "-1"{"last Sunday"} @@ -997,6 +1246,20 @@ en{ "1"{"next Sunday"} } } + sun-narrow{ + relative{ + "-1"{"last Su"} + "0"{"this Su"} + "1"{"next Su"} + } + } + sun-short{ + relative{ + "-1"{"last Sun."} + "0"{"this Sun."} + "1"{"next Sun."} + } + } thu{ relative{ "-1"{"last Thursday"} @@ -1004,6 +1267,20 @@ en{ "1"{"next Thursday"} } } + thu-narrow{ + relative{ + "-1"{"last Th"} + "0"{"this Th"} + "1"{"next Th"} + } + } + thu-short{ + relative{ + "-1"{"last Thu."} + "0"{"this Thu."} + "1"{"next Thu."} + } + } tue{ relative{ "-1"{"last Tuesday"} @@ -1011,6 +1288,20 @@ en{ "1"{"next Tuesday"} } } + tue-narrow{ + relative{ + "-1"{"last Tu"} + "0"{"this Tu"} + "1"{"next Tu"} + } + } + tue-short{ + relative{ + "-1"{"last Tue."} + "0"{"this Tue."} + "1"{"next Tue."} + } + } wed{ relative{ "-1"{"last Wednesday"} @@ -1018,6 +1309,20 @@ en{ "1"{"next Wednesday"} } } + wed-narrow{ + relative{ + "-1"{"last W"} + "0"{"this W"} + "1"{"next W"} + } + } + wed-short{ + relative{ + "-1"{"last Wed."} + "0"{"this Wed."} + "1"{"next Wed."} + } + } week{ dn{"Week"} relative{ @@ -1036,6 +1341,42 @@ en{ } } } + week-narrow{ + dn{"wk."} + relative{ + "-1"{"last wk."} + "0"{"this wk."} + "1"{"next wk."} + } + relativeTime{ + future{ + one{"+{0} wk."} + other{"+{0} wk."} + } + past{ + one{"-{0} wk."} + other{"-{0} wk."} + } + } + } + week-short{ + dn{"wk."} + relative{ + "-1"{"last wk."} + "0"{"this wk."} + "1"{"next wk."} + } + relativeTime{ + future{ + one{"in {0} wk."} + other{"in {0} wk."} + } + past{ + one{"{0} wk. ago"} + other{"{0} wk. ago"} + } + } + } weekday{ dn{"Day of the Week"} } @@ -1057,6 +1398,42 @@ en{ } } } + year-narrow{ + dn{"yr."} + relative{ + "-1"{"last yr."} + "0"{"this yr."} + "1"{"next yr."} + } + relativeTime{ + future{ + one{"+{0} yr."} + other{"+{0} yr."} + } + past{ + one{"-{0} yr."} + other{"-{0} yr."} + } + } + } + year-short{ + dn{"yr."} + relative{ + "-1"{"last yr."} + "0"{"this yr."} + "1"{"next yr."} + } + relativeTime{ + future{ + one{"in {0} yr."} + other{"in {0} yr."} + } + past{ + one{"{0} yr. ago"} + other{"{0} yr. ago"} + } + } + } zone{ dn{"Time Zone"} } diff --git a/icu4c/source/data/locales/root.txt b/icu4c/source/data/locales/root.txt index c31d25299c..460065c8f6 100644 --- a/icu4c/source/data/locales/root.txt +++ b/icu4c/source/data/locales/root.txt @@ -182,7 +182,7 @@ root{ } native{"latn"} } - Version{"2.0.97.37"} + Version{"2.1.2.21"} calendar{ buddhist{ AmPmMarkers:alias{"/LOCALE/calendar/gregorian/AmPmMarkers"} @@ -2003,6 +2003,8 @@ root{ } } } + day-narrow:alias{"/LOCALE/fields/day-short"} + day-short:alias{"/LOCALE/fields/day"} dayperiod{ dn{"Dayperiod"} } @@ -2016,6 +2018,8 @@ root{ "1"{"next Friday"} } } + fri-narrow:alias{"/LOCALE/fields/fri-short"} + fri-short:alias{"/LOCALE/fields/fri"} hour{ dn{"Hour"} relativeTime{ @@ -2027,6 +2031,8 @@ root{ } } } + hour-narrow:alias{"/LOCALE/fields/hour-short"} + hour-short:alias{"/LOCALE/fields/hour"} minute{ dn{"Minute"} relativeTime{ @@ -2038,6 +2044,8 @@ root{ } } } + minute-narrow:alias{"/LOCALE/fields/minute-short"} + minute-short:alias{"/LOCALE/fields/minute"} mon{ relative{ "-1"{"last Monday"} @@ -2045,6 +2053,8 @@ root{ "1"{"next Monday"} } } + mon-narrow:alias{"/LOCALE/fields/mon-short"} + mon-short:alias{"/LOCALE/fields/mon"} month{ dn{"Month"} relative{ @@ -2061,6 +2071,26 @@ root{ } } } + month-narrow:alias{"/LOCALE/fields/month-short"} + month-short:alias{"/LOCALE/fields/month"} + quarter{ + dn{"Quarter"} + relative{ + "-1"{"last quarter"} + "0"{"this quarter"} + "1"{"next quarter"} + } + relativeTime{ + future{ + other{"+{0} Q"} + } + past{ + other{"-{0} Q"} + } + } + } + quarter-narrow:alias{"/LOCALE/fields/quarter-short"} + quarter-short:alias{"/LOCALE/fields/quarter"} sat{ relative{ "-1"{"last Saturday"} @@ -2068,6 +2098,8 @@ root{ "1"{"next Saturday"} } } + sat-narrow:alias{"/LOCALE/fields/sat-short"} + sat-short:alias{"/LOCALE/fields/sat"} second{ dn{"Second"} relative{ @@ -2082,6 +2114,8 @@ root{ } } } + second-narrow:alias{"/LOCALE/fields/second-short"} + second-short:alias{"/LOCALE/fields/second"} sun{ relative{ "-1"{"last Sunday"} @@ -2089,6 +2123,8 @@ root{ "1"{"next Sunday"} } } + sun-narrow:alias{"/LOCALE/fields/sun-short"} + sun-short:alias{"/LOCALE/fields/sun"} thu{ relative{ "-1"{"last Thursday"} @@ -2096,6 +2132,8 @@ root{ "1"{"next Thursday"} } } + thu-narrow:alias{"/LOCALE/fields/thu-short"} + thu-short:alias{"/LOCALE/fields/thu"} tue{ relative{ "-1"{"last Tuesday"} @@ -2103,6 +2141,8 @@ root{ "1"{"next Tuesday"} } } + tue-narrow:alias{"/LOCALE/fields/tue-short"} + tue-short:alias{"/LOCALE/fields/tue"} wed{ relative{ "-1"{"last Wednesday"} @@ -2110,6 +2150,8 @@ root{ "1"{"next Wednesday"} } } + wed-narrow:alias{"/LOCALE/fields/wed-short"} + wed-short:alias{"/LOCALE/fields/wed"} week{ dn{"Week"} relative{ @@ -2126,6 +2168,8 @@ root{ } } } + week-narrow:alias{"/LOCALE/fields/week-short"} + week-short:alias{"/LOCALE/fields/week"} weekday{ dn{"Day of the Week"} } @@ -2145,6 +2189,8 @@ root{ } } } + year-narrow:alias{"/LOCALE/fields/year-short"} + year-short:alias{"/LOCALE/fields/year"} zone{ dn{"Zone"} } diff --git a/icu4c/source/i18n/Makefile.in b/icu4c/source/i18n/Makefile.in index 2cff2ba940..3dc5b5ffdd 100644 --- a/icu4c/source/i18n/Makefile.in +++ b/icu4c/source/i18n/Makefile.in @@ -94,7 +94,7 @@ uspoof.o uspoof_impl.o uspoof_build.o uspoof_conf.o uspoof_wsconf.o decfmtst.o s ztrans.o zrule.o vzone.o fphdlimp.o fpositer.o locdspnm.o \ decNumber.o decContext.o alphaindex.o tznames.o tznames_impl.o tzgnames.o \ tzfmt.o compactdecimalformat.o gender.o region.o scriptset.o identifier_info.o \ -uregion.o reldatefmt.o quantityformatter.o measunit.o filteredbrk.o scientificformathelper.o +uregion.o reldatefmt.o quantityformatter.o measunit.o filteredbrk.o scientificformathelper.o sharedbreakiterator.o ## Header files to install HEADERS = $(srcdir)/unicode/*.h diff --git a/icu4c/source/i18n/i18n.vcxproj b/icu4c/source/i18n/i18n.vcxproj index c5572dbdaa..a84256aa98 100644 --- a/icu4c/source/i18n/i18n.vcxproj +++ b/icu4c/source/i18n/i18n.vcxproj @@ -348,6 +348,7 @@ + @@ -1149,6 +1150,7 @@ + diff --git a/icu4c/source/i18n/i18n.vcxproj.filters b/icu4c/source/i18n/i18n.vcxproj.filters index eee83efeab..73cacd2d82 100644 --- a/icu4c/source/i18n/i18n.vcxproj.filters +++ b/icu4c/source/i18n/i18n.vcxproj.filters @@ -234,6 +234,9 @@ formatting + + formatting + formatting @@ -689,6 +692,9 @@ formatting + + formatting + formatting diff --git a/icu4c/source/i18n/reldatefmt.cpp b/icu4c/source/i18n/reldatefmt.cpp index 1832c4428f..c982a5f812 100644 --- a/icu4c/source/i18n/reldatefmt.cpp +++ b/icu4c/source/i18n/reldatefmt.cpp @@ -18,6 +18,7 @@ #include "unicode/msgfmt.h" #include "unicode/decimfmt.h" #include "unicode/numfmt.h" +#include "unicode/brkiter.h" #include "lrucache.h" #include "uresimp.h" #include "unicode/ures.h" @@ -27,14 +28,21 @@ #include "charstr.h" #include "sharedptr.h" +#include "sharedbreakiterator.h" #include "sharedpluralrules.h" #include "sharednumberformat.h" +#define RELDATE_STYLE_FULL 0 +#define RELDATE_STYLE_SHORT 1 +#define RELDATE_STYLE_NARROW 2 +#define RELDATE_STYLE_COUNT 3 + // Copied from uscript_props.cpp #define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) static icu::LRUCache *gCache = NULL; static UMutex gCacheMutex = U_MUTEX_INITIALIZER; +static UMutex gBrkIterMutex = U_MUTEX_INITIALIZER; static icu::UInitOnce gCacheInitOnce = U_INITONCE_INITIALIZER; U_CDECL_BEGIN @@ -50,6 +58,20 @@ U_CDECL_END U_NAMESPACE_BEGIN +static int32_t getStyleIndex(UDateFormatStyle style) { + switch (style) { + case UDAT_FULL: + case UDAT_LONG: + return 0; + case UDAT_MEDIUM: + return 1; + case UDAT_SHORT: + return 2; + default: + return 0; + } +} + // RelativeDateTimeFormatter specific data for a single locale class RelativeDateTimeCacheData: public SharedObject { public: @@ -57,11 +79,11 @@ public: virtual ~RelativeDateTimeCacheData(); // no numbers: e.g Next Tuesday; Yesterday; etc. - UnicodeString absoluteUnits[UDAT_ABSOLUTE_UNIT_COUNT][UDAT_DIRECTION_COUNT]; + UnicodeString absoluteUnits[RELDATE_STYLE_COUNT][UDAT_ABSOLUTE_UNIT_COUNT][UDAT_DIRECTION_COUNT]; // has numbers: e.g Next Tuesday; Yesterday; etc. For second index, 0 // means past e.g 5 days ago; 1 means future e.g in 5 days. - QuantityFormatter relativeUnits[UDAT_RELATIVE_UNIT_COUNT][2]; + QuantityFormatter relativeUnits[RELDATE_STYLE_COUNT][UDAT_RELATIVE_UNIT_COUNT][2]; void adoptCombinedDateAndTime(MessageFormat *mfToAdopt) { delete combinedDateAndTime; @@ -330,105 +352,226 @@ static void addWeekDay( status); } +static void addTimeUnits( + const UResourceBundle *resource, + const char *path, const char *pathShort, const char *pathNarrow, + UDateRelativeUnit relativeUnit, + UDateAbsoluteUnit absoluteUnit, + RelativeDateTimeCacheData &cacheData, + UErrorCode &status) { + addTimeUnit( + resource, + path, + cacheData.relativeUnits[0][relativeUnit], + cacheData.absoluteUnits[0][absoluteUnit], + status); + addTimeUnit( + resource, + pathShort, + cacheData.relativeUnits[1][relativeUnit], + cacheData.absoluteUnits[1][absoluteUnit], + status); + addTimeUnit( + resource, + pathNarrow, + cacheData.relativeUnits[2][relativeUnit], + cacheData.absoluteUnits[2][absoluteUnit], + status); +} + +static void initRelativeUnits( + const UResourceBundle *resource, + const char *path, const char *pathShort, const char *pathNarrow, + UDateRelativeUnit relativeUnit, + QuantityFormatter relativeUnits[][UDAT_RELATIVE_UNIT_COUNT][2], + UErrorCode &status) { + initRelativeUnit( + resource, + path, + relativeUnits[0][relativeUnit], + status); + initRelativeUnit( + resource, + pathShort, + relativeUnits[1][relativeUnit], + status); + initRelativeUnit( + resource, + pathNarrow, + relativeUnits[2][relativeUnit], + status); +} + +static void addWeekDays( + const UResourceBundle *resource, + const char *path, const char *pathShort, const char *pathNarrow, + const UnicodeString daysOfWeek[][7], + UDateAbsoluteUnit absoluteUnit, + UnicodeString absoluteUnits[][UDAT_ABSOLUTE_UNIT_COUNT][UDAT_DIRECTION_COUNT], + UErrorCode &status) { + addWeekDay( + resource, + path, + daysOfWeek[0], + absoluteUnit, + absoluteUnits[0], + status); + addWeekDay( + resource, + pathShort, + daysOfWeek[1], + absoluteUnit, + absoluteUnits[1], + status); + addWeekDay( + resource, + pathNarrow, + daysOfWeek[2], + absoluteUnit, + absoluteUnits[2], + status); +} + static UBool loadUnitData( const UResourceBundle *resource, RelativeDateTimeCacheData &cacheData, UErrorCode &status) { - addTimeUnit( + addTimeUnits( resource, - "fields/day", - cacheData.relativeUnits[UDAT_RELATIVE_DAYS], - cacheData.absoluteUnits[UDAT_ABSOLUTE_DAY], + "fields/day", "fields/day-short", "fields/day-narrow", + UDAT_RELATIVE_DAYS, + UDAT_ABSOLUTE_DAY, + cacheData, status); - addTimeUnit( + addTimeUnits( resource, - "fields/week", - cacheData.relativeUnits[UDAT_RELATIVE_WEEKS], - cacheData.absoluteUnits[UDAT_ABSOLUTE_WEEK], + "fields/week", "fields/week-short", "fields/week-narrow", + UDAT_RELATIVE_WEEKS, + UDAT_ABSOLUTE_WEEK, + cacheData, status); - addTimeUnit( + addTimeUnits( resource, - "fields/month", - cacheData.relativeUnits[UDAT_RELATIVE_MONTHS], - cacheData.absoluteUnits[UDAT_ABSOLUTE_MONTH], + "fields/month", "fields/month-short", "fields/month-narrow", + UDAT_RELATIVE_MONTHS, + UDAT_ABSOLUTE_MONTH, + cacheData, status); - addTimeUnit( + addTimeUnits( resource, - "fields/year", - cacheData.relativeUnits[UDAT_RELATIVE_YEARS], - cacheData.absoluteUnits[UDAT_ABSOLUTE_YEAR], + "fields/year", "fields/year-short", "fields/year-narrow", + UDAT_RELATIVE_YEARS, + UDAT_ABSOLUTE_YEAR, + cacheData, status); - initRelativeUnit( + initRelativeUnits( resource, - "fields/second", - cacheData.relativeUnits[UDAT_RELATIVE_SECONDS], + "fields/second", "fields/second-short", "fields/second-narrow", + UDAT_RELATIVE_SECONDS, + cacheData.relativeUnits, status); - initRelativeUnit( + initRelativeUnits( resource, - "fields/minute", - cacheData.relativeUnits[UDAT_RELATIVE_MINUTES], + "fields/minute", "fields/minute-short", "fields/minute-narrow", + UDAT_RELATIVE_MINUTES, + cacheData.relativeUnits, status); - initRelativeUnit( + initRelativeUnits( resource, - "fields/hour", - cacheData.relativeUnits[UDAT_RELATIVE_HOURS], + "fields/hour", "fields/hour-short", "fields/hour-narrow", + UDAT_RELATIVE_HOURS, + cacheData.relativeUnits, status); getStringWithFallback( resource, "fields/second/relative/0", - cacheData.absoluteUnits[UDAT_ABSOLUTE_NOW][UDAT_DIRECTION_PLAIN], + cacheData.absoluteUnits[0][UDAT_ABSOLUTE_NOW][UDAT_DIRECTION_PLAIN], status); - UnicodeString daysOfWeek[7]; + getStringWithFallback( + resource, + "fields/second-short/relative/0", + cacheData.absoluteUnits[1][UDAT_ABSOLUTE_NOW][UDAT_DIRECTION_PLAIN], + status); + getStringWithFallback( + resource, + "fields/second-narrow/relative/0", + cacheData.absoluteUnits[2][UDAT_ABSOLUTE_NOW][UDAT_DIRECTION_PLAIN], + status); + UnicodeString daysOfWeek[3][7]; readDaysOfWeek( resource, "calendar/gregorian/dayNames/stand-alone/wide", - daysOfWeek, + daysOfWeek[0], status); - addWeekDay( + readDaysOfWeek( + resource, + "calendar/gregorian/dayNames/stand-alone/short", + daysOfWeek[1], + status); + readDaysOfWeek( + resource, + "calendar/gregorian/dayNames/stand-alone/narrow", + daysOfWeek[2], + status); + addWeekDays( resource, "fields/mon/relative", + "fields/mon-short/relative", + "fields/mon-narrow/relative", daysOfWeek, UDAT_ABSOLUTE_MONDAY, cacheData.absoluteUnits, status); - addWeekDay( + addWeekDays( resource, "fields/tue/relative", + "fields/tue-short/relative", + "fields/tue-narrow/relative", daysOfWeek, UDAT_ABSOLUTE_TUESDAY, cacheData.absoluteUnits, status); - addWeekDay( + addWeekDays( resource, "fields/wed/relative", + "fields/wed-short/relative", + "fields/wed-narrow/relative", daysOfWeek, UDAT_ABSOLUTE_WEDNESDAY, cacheData.absoluteUnits, status); - addWeekDay( + addWeekDays( resource, "fields/thu/relative", + "fields/thu-short/relative", + "fields/thu-narrow/relative", daysOfWeek, UDAT_ABSOLUTE_THURSDAY, cacheData.absoluteUnits, status); - addWeekDay( + addWeekDays( resource, "fields/fri/relative", + "fields/fri-short/relative", + "fields/fri-narrow/relative", daysOfWeek, UDAT_ABSOLUTE_FRIDAY, cacheData.absoluteUnits, status); - addWeekDay( + addWeekDays( resource, "fields/sat/relative", + "fields/sat-short/relative", + "fields/sat-narrow/relative", daysOfWeek, UDAT_ABSOLUTE_SATURDAY, cacheData.absoluteUnits, status); - addWeekDay( + addWeekDays( resource, "fields/sun/relative", + "fields/sun-short/relative", + "fields/sun-narrow/relative", daysOfWeek, UDAT_ABSOLUTE_SUNDAY, cacheData.absoluteUnits, @@ -522,57 +665,127 @@ static UBool getFromCache( return U_SUCCESS(status); } -RelativeDateTimeFormatter::RelativeDateTimeFormatter(UErrorCode& status) - : cache(NULL), numberFormat(NULL), pluralRules(NULL) { - init(Locale::getDefault(), NULL, status); +RelativeDateTimeFormatter::RelativeDateTimeFormatter(UErrorCode& status) : + fCache(NULL), + fNumberFormat(NULL), + fPluralRules(NULL), + fStyle(UDAT_FULL), + fContext(UDISPCTX_CAPITALIZATION_NONE), + fOptBreakIterator(NULL) { + init(NULL, NULL, status); } RelativeDateTimeFormatter::RelativeDateTimeFormatter( - const Locale& locale, UErrorCode& status) - : cache(NULL), numberFormat(NULL), pluralRules(NULL) { - init(locale, NULL, status); + const Locale& locale, UErrorCode& status) : + fCache(NULL), + fNumberFormat(NULL), + fPluralRules(NULL), + fStyle(UDAT_FULL), + fContext(UDISPCTX_CAPITALIZATION_NONE), + fOptBreakIterator(NULL), + fLocale(locale) { + init(NULL, NULL, status); } RelativeDateTimeFormatter::RelativeDateTimeFormatter( - const Locale& locale, NumberFormat *nfToAdopt, UErrorCode& status) - : cache(NULL), numberFormat(NULL), pluralRules(NULL) { - init(locale, nfToAdopt, status); + const Locale& locale, NumberFormat *nfToAdopt, UErrorCode& status) : + fCache(NULL), + fNumberFormat(NULL), + fPluralRules(NULL), + fStyle(UDAT_FULL), + fContext(UDISPCTX_CAPITALIZATION_NONE), + fOptBreakIterator(NULL), + fLocale(locale) { + init(nfToAdopt, NULL, status); +} + +RelativeDateTimeFormatter::RelativeDateTimeFormatter( + const Locale& locale, + NumberFormat *nfToAdopt, + UDateFormatStyle styl, + UDisplayContext capitalizationContext, + UErrorCode& status) : + fCache(NULL), + fNumberFormat(NULL), + fPluralRules(NULL), + fStyle(styl), + fContext(capitalizationContext), + fOptBreakIterator(NULL), + fLocale(locale) { + if (U_FAILURE(status)) { + return; + } + if ((capitalizationContext >> 8) != UDISPCTX_TYPE_CAPITALIZATION) { + status = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + if (capitalizationContext == UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE) { + BreakIterator *bi = BreakIterator::createSentenceInstance(locale, status); + if (U_FAILURE(status)) { + return; + } + init(nfToAdopt, bi, status); + } else { + init(nfToAdopt, NULL, status); + } } RelativeDateTimeFormatter::RelativeDateTimeFormatter( const RelativeDateTimeFormatter& other) - : cache(other.cache), - numberFormat(other.numberFormat), - pluralRules(other.pluralRules) { - cache->addRef(); - numberFormat->addRef(); - pluralRules->addRef(); + : fCache(other.fCache), + fNumberFormat(other.fNumberFormat), + fPluralRules(other.fPluralRules), + fStyle(other.fStyle), + fContext(other.fContext), + fOptBreakIterator(other.fOptBreakIterator), + fLocale(other.fLocale) { + fCache->addRef(); + fNumberFormat->addRef(); + fPluralRules->addRef(); + if (fOptBreakIterator != NULL) { + fOptBreakIterator->addRef(); + } } RelativeDateTimeFormatter& RelativeDateTimeFormatter::operator=( const RelativeDateTimeFormatter& other) { if (this != &other) { - SharedObject::copyPtr(other.cache, cache); - SharedObject::copyPtr(other.numberFormat, numberFormat); - SharedObject::copyPtr(other.pluralRules, pluralRules); + SharedObject::copyPtr(other.fCache, fCache); + SharedObject::copyPtr(other.fNumberFormat, fNumberFormat); + SharedObject::copyPtr(other.fPluralRules, fPluralRules); + SharedObject::copyPtr(other.fOptBreakIterator, fOptBreakIterator); + fStyle = other.fStyle; + fContext = other.fContext; + fLocale = other.fLocale; } return *this; } RelativeDateTimeFormatter::~RelativeDateTimeFormatter() { - if (cache != NULL) { - cache->removeRef(); + if (fCache != NULL) { + fCache->removeRef(); } - if (numberFormat != NULL) { - numberFormat->removeRef(); + if (fNumberFormat != NULL) { + fNumberFormat->removeRef(); } - if (pluralRules != NULL) { - pluralRules->removeRef(); + if (fPluralRules != NULL) { + fPluralRules->removeRef(); + } + if (fOptBreakIterator != NULL) { + fOptBreakIterator->removeRef(); } } const NumberFormat& RelativeDateTimeFormatter::getNumberFormat() const { - return **numberFormat; + return **fNumberFormat; +} + +UDisplayContext RelativeDateTimeFormatter::getCapitalizationContext() const { + return fContext; +} + +UDateFormatStyle RelativeDateTimeFormatter::getFormatStyle() const { + return fStyle; } UnicodeString& RelativeDateTimeFormatter::format( @@ -587,13 +800,25 @@ UnicodeString& RelativeDateTimeFormatter::format( } int32_t bFuture = direction == UDAT_DIRECTION_NEXT ? 1 : 0; FieldPosition pos(FieldPosition::DONT_CARE); - return cache->relativeUnits[unit][bFuture].format( + if (fOptBreakIterator == NULL) { + return fCache->relativeUnits[getStyleIndex(fStyle)][unit][bFuture].format( quantity, - **numberFormat, - **pluralRules, + **fNumberFormat, + **fPluralRules, appendTo, pos, status); + } + UnicodeString result; + fCache->relativeUnits[getStyleIndex(fStyle)][unit][bFuture].format( + quantity, + **fNumberFormat, + **fPluralRules, + result, + pos, + status); + adjustForContext(result); + return appendTo.append(result); } UnicodeString& RelativeDateTimeFormatter::format( @@ -606,7 +831,12 @@ UnicodeString& RelativeDateTimeFormatter::format( status = U_ILLEGAL_ARGUMENT_ERROR; return appendTo; } - return appendTo.append(cache->absoluteUnits[unit][direction]); + if (fOptBreakIterator == NULL) { + return appendTo.append(fCache->absoluteUnits[getStyleIndex(fStyle)][unit][direction]); + } + UnicodeString result(fCache->absoluteUnits[getStyleIndex(fStyle)][unit][direction]); + adjustForContext(result); + return appendTo.append(result); } UnicodeString& RelativeDateTimeFormatter::combineDateAndTime( @@ -614,33 +844,49 @@ UnicodeString& RelativeDateTimeFormatter::combineDateAndTime( UnicodeString& appendTo, UErrorCode& status) const { Formattable args[2] = {timeString, relativeDateString}; FieldPosition fpos(0); - return cache->getCombinedDateAndTime()->format( + return fCache->getCombinedDateAndTime()->format( args, 2, appendTo, fpos, status); } -void RelativeDateTimeFormatter::init( - const Locale &locale, NumberFormat *nfToAdopt, UErrorCode &status) { - LocalPointer nf(nfToAdopt); - if (!getFromCache(locale.getName(), cache, status)) { +void RelativeDateTimeFormatter::adjustForContext(UnicodeString &str) const { + if (fOptBreakIterator == NULL + || str.length() == 0 || !u_islower(str.char32At(0))) { return; } - SharedObject::copyPtr( - PluralRules::createSharedInstance( - locale, UPLURAL_TYPE_CARDINAL, status), - pluralRules); + + // Must guarantee that one thread at a time accesses the shared break + // iterator. + Mutex lock(&gBrkIterMutex); + str.toTitle( + fOptBreakIterator->get(), + fLocale, + U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT); +} + +void RelativeDateTimeFormatter::init( + NumberFormat *nfToAdopt, + BreakIterator *biToAdopt, + UErrorCode &status) { + LocalPointer nf(nfToAdopt); + LocalPointer bi(biToAdopt); + if (!getFromCache(fLocale.getName(), fCache, status)) { + return; + } + const SharedPluralRules *pr = PluralRules::createSharedInstance( + fLocale, UPLURAL_TYPE_CARDINAL, status); if (U_FAILURE(status)) { return; } - pluralRules->removeRef(); + SharedObject::copyPtr(pr, fPluralRules); + pr->removeRef(); if (nf.isNull()) { - SharedObject::copyPtr( - NumberFormat::createSharedInstance( - locale, UNUM_DECIMAL, status), - numberFormat); + const SharedNumberFormat *shared = NumberFormat::createSharedInstance( + fLocale, UNUM_DECIMAL, status); if (U_FAILURE(status)) { return; } - numberFormat->removeRef(); + SharedObject::copyPtr(shared, fNumberFormat); + shared->removeRef(); } else { SharedNumberFormat *shared = new SharedNumberFormat(nf.getAlias()); if (shared == NULL) { @@ -648,7 +894,18 @@ void RelativeDateTimeFormatter::init( return; } nf.orphan(); - SharedObject::copyPtr(shared, numberFormat); + SharedObject::copyPtr(shared, fNumberFormat); + } + if (bi.isNull()) { + SharedObject::clearPtr(fOptBreakIterator); + } else { + SharedBreakIterator *shared = new SharedBreakIterator(bi.getAlias()); + if (shared == NULL) { + status = U_MEMORY_ALLOCATION_ERROR; + return; + } + bi.orphan(); + SharedObject::copyPtr(shared, fOptBreakIterator); } } diff --git a/icu4c/source/i18n/sharedbreakiterator.cpp b/icu4c/source/i18n/sharedbreakiterator.cpp new file mode 100644 index 0000000000..8fa6010077 --- /dev/null +++ b/icu4c/source/i18n/sharedbreakiterator.cpp @@ -0,0 +1,21 @@ +/* +******************************************************************************* +* Copyright (C) 2013-2014, International Business Machines Corporation and * +* others. All Rights Reserved. * +******************************************************************************* +* +* File RELDATEFMTTEST.CPP +* +******************************************************************************* +*/ +#include "sharedbreakiterator.h" +#include "unicode/brkiter.h" + +U_NAMESPACE_BEGIN + +SharedBreakIterator::~SharedBreakIterator() { + delete ptr; +} + +U_NAMESPACE_END + diff --git a/icu4c/source/i18n/sharedbreakiterator.h b/icu4c/source/i18n/sharedbreakiterator.h new file mode 100644 index 0000000000..cae34afd5b --- /dev/null +++ b/icu4c/source/i18n/sharedbreakiterator.h @@ -0,0 +1,43 @@ +/* +****************************************************************************** +* Copyright (C) 2014, International Business Machines +* Corporation and others. All Rights Reserved. +****************************************************************************** +* sharedbreakiterator.h +*/ + +#ifndef __SHARED_BREAKITERATOR_H__ +#define __SHARED_BREAKITERATOR_H__ + +#include "unicode/utypes.h" +#include "sharedobject.h" + +U_NAMESPACE_BEGIN + +class BreakIterator; + +// SharedBreakIterator encapsulates a shared BreakIterator. Because +// BreakIterator has mutable semantics, clients must ensure that all uses +// of a particular shared BreakIterator is protected by the same mutex +// ensuring that only one thread at a time gets access to that shared +// BreakIterator. Clients can accomplish this by creating a mutex for all +// uses of break iterator within a particular class. Then objects of that +// class may then freely share break iterators among themselves. However, +// these shared break iterators must never be exposed outside of that class. +class U_I18N_API SharedBreakIterator : public SharedObject { +public: + SharedBreakIterator(BreakIterator *biToAdopt) : ptr(biToAdopt) { } + virtual ~SharedBreakIterator(); + + BreakIterator *get() const { return ptr; } + BreakIterator *operator->() const { return ptr; } + BreakIterator &operator*() const { return *ptr; } +private: + BreakIterator *ptr; + SharedBreakIterator(const SharedBreakIterator &); + SharedBreakIterator &operator=(const SharedBreakIterator &); +}; + +U_NAMESPACE_END + +#endif diff --git a/icu4c/source/i18n/unicode/reldatefmt.h b/icu4c/source/i18n/unicode/reldatefmt.h index ee7a176e5a..bbff21194c 100644 --- a/icu4c/source/i18n/unicode/reldatefmt.h +++ b/icu4c/source/i18n/unicode/reldatefmt.h @@ -14,6 +14,9 @@ #include "unicode/utypes.h" #include "unicode/uobject.h" +#include "unicode/udisplaycontext.h" +#include "unicode/udat.h" +#include "unicode/locid.h" /** * \file @@ -220,10 +223,10 @@ typedef enum UDateDirection { U_NAMESPACE_BEGIN -class Locale; class RelativeDateTimeCacheData; class SharedNumberFormat; class SharedPluralRules; +class SharedBreakIterator; class NumberFormat; class UnicodeString; @@ -295,8 +298,6 @@ class UnicodeString; * * @draft ICU 53 */ - - class U_I18N_API RelativeDateTimeFormatter : public UObject { public: @@ -325,6 +326,29 @@ public: RelativeDateTimeFormatter( const Locale& locale, NumberFormat *nfToAdopt, UErrorCode& status); + /** + * Create RelativeDateTimeFormatter with given locale, NumberFormat, + * and capitalization context. + * + * @param locale the locale + * @param nfToAdopt Constructed object takes ownership of this pointer. + * It is an error for caller to delete this pointer or change its + * contents after calling this constructor. Caller may pass NULL for + * this argument if they want default number format behavior. + * @param style the format style. The UDAT_RELATIVE bit field has no effect. + * @param capitalizationContext The capitalization context must start with + * U_DISPCTX_CAPITALIZATION_. Otherwise status is set to + * U_ILLEGAL_ARGUMENT_ERROR + * @status Any error is returned here. + * @draft ICU 53 + */ + RelativeDateTimeFormatter( + const Locale& locale, + NumberFormat *nfToAdopt, + UDateFormatStyle style, + UDisplayContext capitalizationContext, + UErrorCode& status); + /** * Copy constructor. * @draft ICU 53 @@ -409,11 +433,32 @@ public: */ const NumberFormat& getNumberFormat() const; + /** + * Returns the capitalization context. + * + * @draft ICU 54 + */ + UDisplayContext getCapitalizationContext() const; + + /** + * Returns the format style. + * + * @draft ICU 54 + */ + UDateFormatStyle getFormatStyle() const; private: - const RelativeDateTimeCacheData* cache; - const SharedNumberFormat *numberFormat; - const SharedPluralRules *pluralRules; - void init(const Locale &, NumberFormat *nfToAdopt, UErrorCode &status); + const RelativeDateTimeCacheData* fCache; + const SharedNumberFormat *fNumberFormat; + const SharedPluralRules *fPluralRules; + UDateFormatStyle fStyle; + UDisplayContext fContext; + const SharedBreakIterator *fOptBreakIterator; + Locale fLocale; + void init( + NumberFormat *nfToAdopt, + BreakIterator *brkIter, + UErrorCode &status); + void adjustForContext(UnicodeString &) const; }; U_NAMESPACE_END diff --git a/icu4c/source/test/intltest/reldatefmttest.cpp b/icu4c/source/test/intltest/reldatefmttest.cpp index ce2ffc0aea..eeda64c6d6 100644 --- a/icu4c/source/test/intltest/reldatefmttest.cpp +++ b/icu4c/source/test/intltest/reldatefmttest.cpp @@ -98,6 +98,186 @@ static WithQuantityExpected kEnglish[] = { {2.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_YEARS, "2 years ago"} }; +static WithQuantityExpected kEnglishCaps[] = { + {0.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_SECONDS, "In 0 seconds"}, + {0.5, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_SECONDS, "In 0.5 seconds"}, + {1.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_SECONDS, "In 1 second"}, + {2.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_SECONDS, "In 2 seconds"}, + {0.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MINUTES, "In 0 minutes"}, + {0.5, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MINUTES, "In 0.5 minutes"}, + {1.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MINUTES, "In 1 minute"}, + {2.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MINUTES, "In 2 minutes"}, + {0.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_HOURS, "In 0 hours"}, + {0.5, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_HOURS, "In 0.5 hours"}, + {1.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_HOURS, "In 1 hour"}, + {2.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_HOURS, "In 2 hours"}, + {0.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_DAYS, "In 0 days"}, + {0.5, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_DAYS, "In 0.5 days"}, + {1.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_DAYS, "In 1 day"}, + {2.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_DAYS, "In 2 days"}, + {0.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_WEEKS, "In 0 weeks"}, + {0.5, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_WEEKS, "In 0.5 weeks"}, + {1.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_WEEKS, "In 1 week"}, + {2.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_WEEKS, "In 2 weeks"}, + {0.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MONTHS, "In 0 months"}, + {0.5, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MONTHS, "In 0.5 months"}, + {1.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MONTHS, "In 1 month"}, + {2.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MONTHS, "In 2 months"}, + {0.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_YEARS, "In 0 years"}, + {0.5, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_YEARS, "In 0.5 years"}, + {1.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_YEARS, "In 1 year"}, + {2.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_YEARS, "In 2 years"}, + + {0.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_SECONDS, "0 seconds ago"}, + {0.5, UDAT_DIRECTION_LAST, UDAT_RELATIVE_SECONDS, "0.5 seconds ago"}, + {1.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_SECONDS, "1 second ago"}, + {2.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_SECONDS, "2 seconds ago"}, + {0.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_MINUTES, "0 minutes ago"}, + {0.5, UDAT_DIRECTION_LAST, UDAT_RELATIVE_MINUTES, "0.5 minutes ago"}, + {1.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_MINUTES, "1 minute ago"}, + {2.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_MINUTES, "2 minutes ago"}, + {0.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_HOURS, "0 hours ago"}, + {0.5, UDAT_DIRECTION_LAST, UDAT_RELATIVE_HOURS, "0.5 hours ago"}, + {1.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_HOURS, "1 hour ago"}, + {2.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_HOURS, "2 hours ago"}, + {0.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_DAYS, "0 days ago"}, + {0.5, UDAT_DIRECTION_LAST, UDAT_RELATIVE_DAYS, "0.5 days ago"}, + {1.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_DAYS, "1 day ago"}, + {2.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_DAYS, "2 days ago"}, + {0.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_WEEKS, "0 weeks ago"}, + {0.5, UDAT_DIRECTION_LAST, UDAT_RELATIVE_WEEKS, "0.5 weeks ago"}, + {1.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_WEEKS, "1 week ago"}, + {2.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_WEEKS, "2 weeks ago"}, + {0.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_MONTHS, "0 months ago"}, + {0.5, UDAT_DIRECTION_LAST, UDAT_RELATIVE_MONTHS, "0.5 months ago"}, + {1.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_MONTHS, "1 month ago"}, + {2.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_MONTHS, "2 months ago"}, + {0.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_YEARS, "0 years ago"}, + {0.5, UDAT_DIRECTION_LAST, UDAT_RELATIVE_YEARS, "0.5 years ago"}, + {1.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_YEARS, "1 year ago"}, + {2.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_YEARS, "2 years ago"} +}; + +static WithQuantityExpected kEnglishShort[] = { + {0.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_SECONDS, "in 0 sec."}, + {0.5, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_SECONDS, "in 0.5 sec."}, + {1.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_SECONDS, "in 1 sec."}, + {2.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_SECONDS, "in 2 sec."}, + {0.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MINUTES, "in 0 min."}, + {0.5, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MINUTES, "in 0.5 min."}, + {1.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MINUTES, "in 1 min."}, + {2.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MINUTES, "in 2 min."}, + {0.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_HOURS, "in 0 hr."}, + {0.5, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_HOURS, "in 0.5 hr."}, + {1.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_HOURS, "in 1 hr."}, + {2.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_HOURS, "in 2 hr."}, + {0.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_DAYS, "in 0 days"}, + {0.5, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_DAYS, "in 0.5 days"}, + {1.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_DAYS, "in 1 day"}, + {2.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_DAYS, "in 2 days"}, + {0.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_WEEKS, "in 0 wk."}, + {0.5, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_WEEKS, "in 0.5 wk."}, + {1.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_WEEKS, "in 1 wk."}, + {2.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_WEEKS, "in 2 wk."}, + {0.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MONTHS, "in 0 mo."}, + {0.5, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MONTHS, "in 0.5 mo."}, + {1.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MONTHS, "in 1 mo."}, + {2.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MONTHS, "in 2 mo."}, + {0.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_YEARS, "in 0 yr."}, + {0.5, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_YEARS, "in 0.5 yr."}, + {1.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_YEARS, "in 1 yr."}, + {2.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_YEARS, "in 2 yr."}, + + {0.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_SECONDS, "0 sec. ago"}, + {0.5, UDAT_DIRECTION_LAST, UDAT_RELATIVE_SECONDS, "0.5 sec. ago"}, + {1.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_SECONDS, "1 sec. ago"}, + {2.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_SECONDS, "2 sec. ago"}, + {0.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_MINUTES, "0 min. ago"}, + {0.5, UDAT_DIRECTION_LAST, UDAT_RELATIVE_MINUTES, "0.5 min. ago"}, + {1.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_MINUTES, "1 min. ago"}, + {2.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_MINUTES, "2 min. ago"}, + {0.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_HOURS, "0 hr. ago"}, + {0.5, UDAT_DIRECTION_LAST, UDAT_RELATIVE_HOURS, "0.5 hr. ago"}, + {1.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_HOURS, "1 hr. ago"}, + {2.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_HOURS, "2 hr. ago"}, + {0.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_DAYS, "0 days ago"}, + {0.5, UDAT_DIRECTION_LAST, UDAT_RELATIVE_DAYS, "0.5 days ago"}, + {1.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_DAYS, "1 day ago"}, + {2.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_DAYS, "2 days ago"}, + {0.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_WEEKS, "0 wk. ago"}, + {0.5, UDAT_DIRECTION_LAST, UDAT_RELATIVE_WEEKS, "0.5 wk. ago"}, + {1.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_WEEKS, "1 wk. ago"}, + {2.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_WEEKS, "2 wk. ago"}, + {0.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_MONTHS, "0 mo. ago"}, + {0.5, UDAT_DIRECTION_LAST, UDAT_RELATIVE_MONTHS, "0.5 mo. ago"}, + {1.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_MONTHS, "1 mo. ago"}, + {2.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_MONTHS, "2 mo. ago"}, + {0.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_YEARS, "0 yr. ago"}, + {0.5, UDAT_DIRECTION_LAST, UDAT_RELATIVE_YEARS, "0.5 yr. ago"}, + {1.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_YEARS, "1 yr. ago"}, + {2.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_YEARS, "2 yr. ago"} +}; + +static WithQuantityExpected kEnglishNarrow[] = { + {0.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_SECONDS, "+0 s"}, + {0.5, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_SECONDS, "+0.5 s"}, + {1.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_SECONDS, "+1 s"}, + {2.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_SECONDS, "+2 s"}, + {0.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MINUTES, "+0 m"}, + {0.5, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MINUTES, "+0.5 m"}, + {1.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MINUTES, "+1 m"}, + {2.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MINUTES, "+2 m"}, + {0.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_HOURS, "+0 h"}, + {0.5, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_HOURS, "+0.5 h"}, + {1.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_HOURS, "+1 h"}, + {2.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_HOURS, "+2 h"}, + {0.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_DAYS, "+0 days"}, + {0.5, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_DAYS, "+0.5 days"}, + {1.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_DAYS, "+1 day"}, + {2.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_DAYS, "+2 days"}, + {0.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_WEEKS, "+0 wk."}, + {0.5, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_WEEKS, "+0.5 wk."}, + {1.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_WEEKS, "+1 wk."}, + {2.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_WEEKS, "+2 wk."}, + {0.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MONTHS, "+0 mo."}, + {0.5, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MONTHS, "+0.5 mo."}, + {1.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MONTHS, "+1 mo."}, + {2.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_MONTHS, "+2 mo."}, + {0.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_YEARS, "+0 yr."}, + {0.5, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_YEARS, "+0.5 yr."}, + {1.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_YEARS, "+1 yr."}, + {2.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_YEARS, "+2 yr."}, + + {0.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_SECONDS, "-0 s"}, + {0.5, UDAT_DIRECTION_LAST, UDAT_RELATIVE_SECONDS, "-0.5 s"}, + {1.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_SECONDS, "-1 s"}, + {2.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_SECONDS, "-2 s"}, + {0.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_MINUTES, "-0 m"}, + {0.5, UDAT_DIRECTION_LAST, UDAT_RELATIVE_MINUTES, "-0.5 m"}, + {1.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_MINUTES, "-1 m"}, + {2.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_MINUTES, "-2 m"}, + {0.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_HOURS, "-0 h"}, + {0.5, UDAT_DIRECTION_LAST, UDAT_RELATIVE_HOURS, "-0.5 h"}, + {1.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_HOURS, "-1 h"}, + {2.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_HOURS, "-2 h"}, + {0.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_DAYS, "-0 days"}, + {0.5, UDAT_DIRECTION_LAST, UDAT_RELATIVE_DAYS, "-0.5 days"}, + {1.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_DAYS, "-1 day"}, + {2.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_DAYS, "-2 days"}, + {0.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_WEEKS, "-0 wk."}, + {0.5, UDAT_DIRECTION_LAST, UDAT_RELATIVE_WEEKS, "-0.5 wk."}, + {1.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_WEEKS, "-1 wk."}, + {2.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_WEEKS, "-2 wk."}, + {0.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_MONTHS, "-0 mo."}, + {0.5, UDAT_DIRECTION_LAST, UDAT_RELATIVE_MONTHS, "-0.5 mo."}, + {1.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_MONTHS, "-1 mo."}, + {2.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_MONTHS, "-2 mo."}, + {0.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_YEARS, "-0 yr."}, + {0.5, UDAT_DIRECTION_LAST, UDAT_RELATIVE_YEARS, "-0.5 yr."}, + {1.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_YEARS, "-1 yr."}, + {2.0, UDAT_DIRECTION_LAST, UDAT_RELATIVE_YEARS, "-2 yr."} +}; + static WithQuantityExpected kEnglishDecimal[] = { {0.0, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_SECONDS, "in 0.0 seconds"}, {0.5, UDAT_DIRECTION_NEXT, UDAT_RELATIVE_SECONDS, "in 0.5 seconds"}, @@ -167,6 +347,174 @@ static WithoutQuantityExpected kEnglishNoQuantity[] = { {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_NOW, "now"} }; +static WithoutQuantityExpected kEnglishNoQuantityCaps[] = { + {UDAT_DIRECTION_NEXT_2, UDAT_ABSOLUTE_DAY, ""}, + + {UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_DAY, "Tomorrow"}, + {UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_WEEK, "Next week"}, + {UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_MONTH, "Next month"}, + {UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_YEAR, "Next year"}, + {UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_MONDAY, "Next Monday"}, + {UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_TUESDAY, "Next Tuesday"}, + {UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_WEDNESDAY, "Next Wednesday"}, + {UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_THURSDAY, "Next Thursday"}, + {UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_FRIDAY, "Next Friday"}, + {UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_SATURDAY, "Next Saturday"}, + {UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_SUNDAY, "Next Sunday"}, + + {UDAT_DIRECTION_LAST_2, UDAT_ABSOLUTE_DAY, ""}, + + {UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_DAY, "Yesterday"}, + {UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_WEEK, "Last week"}, + {UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_MONTH, "Last month"}, + {UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_YEAR, "Last year"}, + {UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_MONDAY, "Last Monday"}, + {UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_TUESDAY, "Last Tuesday"}, + {UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_WEDNESDAY, "Last Wednesday"}, + {UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_THURSDAY, "Last Thursday"}, + {UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_FRIDAY, "Last Friday"}, + {UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_SATURDAY, "Last Saturday"}, + {UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_SUNDAY, "Last Sunday"}, + + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_DAY, "Today"}, + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_WEEK, "This week"}, + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_MONTH, "This month"}, + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_YEAR, "This year"}, + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_MONDAY, "This Monday"}, + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_TUESDAY, "This Tuesday"}, + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_WEDNESDAY, "This Wednesday"}, + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_THURSDAY, "This Thursday"}, + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_FRIDAY, "This Friday"}, + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_SATURDAY, "This Saturday"}, + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_SUNDAY, "This Sunday"}, + + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_DAY, "Day"}, + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_WEEK, "Week"}, + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_MONTH, "Month"}, + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_YEAR, "Year"}, + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_MONDAY, "Monday"}, + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_TUESDAY, "Tuesday"}, + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_WEDNESDAY, "Wednesday"}, + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_THURSDAY, "Thursday"}, + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_FRIDAY, "Friday"}, + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_SATURDAY, "Saturday"}, + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_SUNDAY, "Sunday"}, + + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_NOW, "Now"} +}; + +static WithoutQuantityExpected kEnglishNoQuantityShort[] = { + {UDAT_DIRECTION_NEXT_2, UDAT_ABSOLUTE_DAY, ""}, + + {UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_DAY, "tomorrow"}, + {UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_WEEK, "next wk."}, + {UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_MONTH, "next mo."}, + {UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_YEAR, "next yr."}, + {UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_MONDAY, "next Mon."}, + {UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_TUESDAY, "next Tue."}, + {UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_WEDNESDAY, "next Wed."}, + {UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_THURSDAY, "next Thu."}, + {UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_FRIDAY, "next Fri."}, + {UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_SATURDAY, "next Sat."}, + {UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_SUNDAY, "next Sun."}, + + {UDAT_DIRECTION_LAST_2, UDAT_ABSOLUTE_DAY, ""}, + + {UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_DAY, "yesterday"}, + {UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_WEEK, "last wk."}, + {UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_MONTH, "last mo."}, + {UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_YEAR, "last yr."}, + {UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_MONDAY, "last Mon."}, + {UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_TUESDAY, "last Tue."}, + {UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_WEDNESDAY, "last Wed."}, + {UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_THURSDAY, "last Thu."}, + {UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_FRIDAY, "last Fri."}, + {UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_SATURDAY, "last Sat."}, + {UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_SUNDAY, "last Sun."}, + + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_DAY, "today"}, + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_WEEK, "this wk."}, + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_MONTH, "this mo."}, + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_YEAR, "this yr."}, + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_MONDAY, "this Mon."}, + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_TUESDAY, "this Tue."}, + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_WEDNESDAY, "this Wed."}, + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_THURSDAY, "this Thu."}, + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_FRIDAY, "this Fri."}, + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_SATURDAY, "this Sat."}, + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_SUNDAY, "this Sun."}, + + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_DAY, "day"}, + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_WEEK, "wk."}, + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_MONTH, "mo."}, + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_YEAR, "yr."}, + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_MONDAY, "Mo"}, + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_TUESDAY, "Tu"}, + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_WEDNESDAY, "We"}, + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_THURSDAY, "Th"}, + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_FRIDAY, "Fr"}, + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_SATURDAY, "Sa"}, + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_SUNDAY, "Su"}, + + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_NOW, "now"} +}; + +static WithoutQuantityExpected kEnglishNoQuantityNarrow[] = { + {UDAT_DIRECTION_NEXT_2, UDAT_ABSOLUTE_DAY, ""}, + + {UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_DAY, "tomorrow"}, + {UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_WEEK, "next wk."}, + {UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_MONTH, "next mo."}, + {UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_YEAR, "next yr."}, + {UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_MONDAY, "next M"}, + {UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_TUESDAY, "next Tu"}, + {UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_WEDNESDAY, "next W"}, + {UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_THURSDAY, "next Th"}, + {UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_FRIDAY, "next F"}, + {UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_SATURDAY, "next Sa"}, + {UDAT_DIRECTION_NEXT, UDAT_ABSOLUTE_SUNDAY, "next Su"}, + + {UDAT_DIRECTION_LAST_2, UDAT_ABSOLUTE_DAY, ""}, + + {UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_DAY, "yesterday"}, + {UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_WEEK, "last wk."}, + {UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_MONTH, "last mo."}, + {UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_YEAR, "last yr."}, + {UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_MONDAY, "last M"}, + {UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_TUESDAY, "last Tu"}, + {UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_WEDNESDAY, "last W"}, + {UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_THURSDAY, "last Th"}, + {UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_FRIDAY, "last F"}, + {UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_SATURDAY, "last Sa"}, + {UDAT_DIRECTION_LAST, UDAT_ABSOLUTE_SUNDAY, "last Su"}, + + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_DAY, "today"}, + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_WEEK, "this wk."}, + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_MONTH, "this mo."}, + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_YEAR, "this yr."}, + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_MONDAY, "this M"}, + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_TUESDAY, "this Tu"}, + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_WEDNESDAY, "this W"}, + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_THURSDAY, "this Th"}, + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_FRIDAY, "this F"}, + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_SATURDAY, "this Sa"}, + {UDAT_DIRECTION_THIS, UDAT_ABSOLUTE_SUNDAY, "this Su"}, + + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_DAY, "day"}, + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_WEEK, "wk."}, + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_MONTH, "mo."}, + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_YEAR, "yr."}, + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_MONDAY, "M"}, + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_TUESDAY, "T"}, + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_WEDNESDAY, "W"}, + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_THURSDAY, "T"}, + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_FRIDAY, "F"}, + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_SATURDAY, "S"}, + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_SUNDAY, "S"}, + + {UDAT_DIRECTION_PLAIN, UDAT_ABSOLUTE_NOW, "now"} +}; + static WithoutQuantityExpected kSpanishNoQuantity[] = { {UDAT_DIRECTION_NEXT_2, UDAT_ABSOLUTE_DAY, "pasado ma\\u00F1ana"}, {UDAT_DIRECTION_LAST_2, UDAT_ABSOLUTE_DAY, "antes de ayer"} @@ -180,19 +528,38 @@ public: void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par=0); private: void TestEnglish(); + void TestEnglishCaps(); + void TestEnglishShort(); + void TestEnglishNarrow(); void TestSerbian(); + void TestSerbianFallback(); void TestEnglishNoQuantity(); + void TestEnglishNoQuantityCaps(); + void TestEnglishNoQuantityShort(); + void TestEnglishNoQuantityNarrow(); void TestSpanishNoQuantity(); void TestFormatWithQuantityIllegalArgument(); void TestFormatWithoutQuantityIllegalArgument(); void TestCustomNumberFormat(); + void TestGetters(); void TestCombineDateAndTime(); + void TestBadDisplayContext(); void RunTest( const Locale& locale, const WithQuantityExpected* expectedResults, int32_t expectedResultLength); void RunTest( const Locale& locale, + UDateFormatStyle style, + const WithQuantityExpected* expectedResults, + int32_t expectedResultLength); + void RunTest( + const Locale& locale, + const WithoutQuantityExpected* expectedResults, + int32_t expectedResultLength); + void RunTest( + const Locale& locale, + UDateFormatStyle style, const WithoutQuantityExpected* expectedResults, int32_t expectedResultLength); void RunTest( @@ -230,13 +597,22 @@ void RelativeDateTimeFormatterTest::runIndexedTest( } TESTCASE_AUTO_BEGIN; TESTCASE_AUTO(TestEnglish); + TESTCASE_AUTO(TestEnglishCaps); + TESTCASE_AUTO(TestEnglishShort); + TESTCASE_AUTO(TestEnglishNarrow); TESTCASE_AUTO(TestSerbian); + TESTCASE_AUTO(TestSerbianFallback); TESTCASE_AUTO(TestEnglishNoQuantity); + TESTCASE_AUTO(TestEnglishNoQuantityCaps); + TESTCASE_AUTO(TestEnglishNoQuantityShort); + TESTCASE_AUTO(TestEnglishNoQuantityNarrow); TESTCASE_AUTO(TestSpanishNoQuantity); TESTCASE_AUTO(TestFormatWithQuantityIllegalArgument); TESTCASE_AUTO(TestFormatWithoutQuantityIllegalArgument); TESTCASE_AUTO(TestCustomNumberFormat); + TESTCASE_AUTO(TestGetters); TESTCASE_AUTO(TestCombineDateAndTime); + TESTCASE_AUTO(TestBadDisplayContext); TESTCASE_AUTO_END; } @@ -244,14 +620,75 @@ void RelativeDateTimeFormatterTest::TestEnglish() { RunTest("en", kEnglish, LENGTHOF(kEnglish)); } +void RelativeDateTimeFormatterTest::TestEnglishCaps() { + UErrorCode status = U_ZERO_ERROR; + RelativeDateTimeFormatter fmt( + "en", + NULL, + UDAT_FULL, + UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, + status); + RelativeDateTimeFormatter fmt3(status); + + // Test assignment and copy constructor with capitalization on. + RelativeDateTimeFormatter fmt2(fmt); + fmt3 = fmt2; + assertSuccess("", status); + RunTest(fmt3, kEnglishCaps, LENGTHOF(kEnglishCaps), "en caps"); +} + +void RelativeDateTimeFormatterTest::TestEnglishShort() { + RunTest("en", UDAT_MEDIUM, kEnglishShort, LENGTHOF(kEnglishShort)); +} + +void RelativeDateTimeFormatterTest::TestEnglishNarrow() { + RunTest("en", UDAT_SHORT, kEnglishNarrow, LENGTHOF(kEnglishNarrow)); +} + void RelativeDateTimeFormatterTest::TestSerbian() { RunTest("sr", kSerbian, LENGTHOF(kSerbian)); } +void RelativeDateTimeFormatterTest::TestSerbianFallback() { + RunTest("sr", UDAT_SHORT, kSerbian, LENGTHOF(kSerbian)); +} + void RelativeDateTimeFormatterTest::TestEnglishNoQuantity() { RunTest("en", kEnglishNoQuantity, LENGTHOF(kEnglishNoQuantity)); } +void RelativeDateTimeFormatterTest::TestEnglishNoQuantityCaps() { + UErrorCode status = U_ZERO_ERROR; + RelativeDateTimeFormatter fmt( + "en", + NULL, + UDAT_FULL, + UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, + status); + assertSuccess("", status); + RunTest( + fmt, + kEnglishNoQuantityCaps, + LENGTHOF(kEnglishNoQuantityCaps), + "en caps no quantity"); +} + +void RelativeDateTimeFormatterTest::TestEnglishNoQuantityShort() { + RunTest( + "en", + UDAT_MEDIUM, + kEnglishNoQuantityShort, + LENGTHOF(kEnglishNoQuantityShort)); +} + +void RelativeDateTimeFormatterTest::TestEnglishNoQuantityNarrow() { + RunTest( + "en", + UDAT_SHORT, + kEnglishNoQuantityNarrow, + LENGTHOF(kEnglishNoQuantityNarrow)); +} + void RelativeDateTimeFormatterTest::TestSpanishNoQuantity() { RunTest("es", kSpanishNoQuantity, LENGTHOF(kSpanishNoQuantity)); } @@ -305,6 +742,27 @@ void RelativeDateTimeFormatterTest::TestCustomNumberFormat() { } +void RelativeDateTimeFormatterTest::TestGetters() { + UErrorCode status = U_ZERO_ERROR; + RelativeDateTimeFormatter fmt( + "en", + NULL, + UDAT_SHORT, + UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, + status); + RelativeDateTimeFormatter fmt3(status); + + // copy and assignment. + RelativeDateTimeFormatter fmt2(fmt); + fmt3 = fmt2; + assertEquals("style", UDAT_SHORT, fmt3.getFormatStyle()); + assertEquals( + "context", + UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, + fmt3.getCapitalizationContext()); + assertSuccess("", status); +} + void RelativeDateTimeFormatterTest::TestCombineDateAndTime() { UErrorCode status = U_ZERO_ERROR; RelativeDateTimeFormatter fmt("en", status); @@ -324,6 +782,16 @@ void RelativeDateTimeFormatterTest::TestCombineDateAndTime() { } } +void RelativeDateTimeFormatterTest::TestBadDisplayContext() { + UErrorCode status = U_ZERO_ERROR; + RelativeDateTimeFormatter fmt( + "en", NULL, UDAT_FULL, UDISPCTX_STANDARD_NAMES, status); + if (status != U_ILLEGAL_ARGUMENT_ERROR) { + errln("Expected U_ILLEGAL_ARGUMENT_ERROR, got %s", u_errorName(status)); + } +} + + void RelativeDateTimeFormatterTest::RunTest( const Locale& locale, @@ -334,7 +802,22 @@ void RelativeDateTimeFormatterTest::RunTest( if (U_FAILURE(status)) { dataerrln("Unable to create format object - %s", u_errorName(status)); return; - } + } + RunTest(fmt, expectedResults, expectedResultLength, locale.getName()); +} + +void RelativeDateTimeFormatterTest::RunTest( + const Locale& locale, + UDateFormatStyle style, + const WithQuantityExpected* expectedResults, + int32_t expectedResultLength) { + UErrorCode status = U_ZERO_ERROR; + RelativeDateTimeFormatter fmt( + locale, NULL, style, UDISPCTX_CAPITALIZATION_NONE, status); + if (U_FAILURE(status)) { + dataerrln("Unable to create format object - %s", u_errorName(status)); + return; + } RunTest(fmt, expectedResults, expectedResultLength, locale.getName()); } @@ -351,6 +834,21 @@ void RelativeDateTimeFormatterTest::RunTest( RunTest(fmt, expectedResults, expectedResultLength, locale.getName()); } +void RelativeDateTimeFormatterTest::RunTest( + const Locale& locale, + UDateFormatStyle style, + const WithoutQuantityExpected* expectedResults, + int32_t expectedResultLength) { + UErrorCode status = U_ZERO_ERROR; + RelativeDateTimeFormatter fmt( + locale, NULL, style, UDISPCTX_CAPITALIZATION_NONE, status); + if (U_FAILURE(status)) { + dataerrln("Unable to create format object - %s", u_errorName(status)); + return; + } + RunTest(fmt, expectedResults, expectedResultLength, locale.getName()); +} + void RelativeDateTimeFormatterTest::RunTest( const RelativeDateTimeFormatter& fmt, const WithQuantityExpected* expectedResults, diff --git a/icu4c/source/test/testdata/structLocale.txt b/icu4c/source/test/testdata/structLocale.txt index ae6b52e727..f6d5e5bfcb 100644 --- a/icu4c/source/test/testdata/structLocale.txt +++ b/icu4c/source/test/testdata/structLocale.txt @@ -3983,6 +3983,66 @@ structLocale:table(nofallback){ } } } + day-narrow{ + dn{"Day"} + relative{ + "-3"{""} + "-2"{""} + "-1"{""} + "0"{""} + "1"{""} + "2"{""} + "3"{""} + } + relativeTime{ + future{ + zero{""} + one{""} + two{""} + few{""} + many{""} + other{""} + } + past{ + zero{""} + one{""} + two{""} + few{""} + many{""} + other{""} + } + } + } + day-short{ + dn{"Day"} + relative{ + "-3"{""} + "-2"{""} + "-1"{""} + "0"{""} + "1"{""} + "2"{""} + "3"{""} + } + relativeTime{ + future{ + zero{""} + one{""} + two{""} + few{""} + many{""} + other{""} + } + past{ + zero{""} + one{""} + two{""} + few{""} + many{""} + other{""} + } + } + } dayperiod{ dn{"Dayperiod"} relative{ @@ -4006,6 +4066,20 @@ structLocale:table(nofallback){ "1"{""} } } + fri-narrow{ + relative{ + "-1"{""} + "0"{""} + "1"{""} + } + } + fri-short{ + relative{ + "-1"{""} + "0"{""} + "1"{""} + } + } hour{ dn{"Hour"} relative{ @@ -4032,6 +4106,58 @@ structLocale:table(nofallback){ } } } + hour-narrow{ + dn{"Hour"} + relative{ + "-1"{""} + "0"{""} + "1"{""} + } + relativeTime{ + future{ + zero{""} + one{""} + two{""} + few{""} + many{""} + other{""} + } + past{ + zero{""} + one{""} + two{""} + few{""} + many{""} + other{""} + } + } + } + hour-short{ + dn{"Hour"} + relative{ + "-1"{""} + "0"{""} + "1"{""} + } + relativeTime{ + future{ + zero{""} + one{""} + two{""} + few{""} + many{""} + other{""} + } + past{ + zero{""} + one{""} + two{""} + few{""} + many{""} + other{""} + } + } + } minute{ dn{"Minute"} relative{ @@ -4058,6 +4184,58 @@ structLocale:table(nofallback){ } } } + minute-narrow{ + dn{"Minute"} + relative{ + "-1"{""} + "0"{""} + "1"{""} + } + relativeTime{ + future{ + zero{""} + one{""} + two{""} + few{""} + many{""} + other{""} + } + past{ + zero{""} + one{""} + two{""} + few{""} + many{""} + other{""} + } + } + } + minute-short{ + dn{"Minute"} + relative{ + "-1"{""} + "0"{""} + "1"{""} + } + relativeTime{ + future{ + zero{""} + one{""} + two{""} + few{""} + many{""} + other{""} + } + past{ + zero{""} + one{""} + two{""} + few{""} + many{""} + other{""} + } + } + } mon{ relative{ "-1"{""} @@ -4065,6 +4243,20 @@ structLocale:table(nofallback){ "1"{""} } } + mon-narrow{ + relative{ + "-1"{""} + "0"{""} + "1"{""} + } + } + mon-short{ + relative{ + "-1"{""} + "0"{""} + "1"{""} + } + } month{ dn{"Month"} relative{ @@ -4091,6 +4283,136 @@ structLocale:table(nofallback){ } } } + month-narrow{ + dn{"Month"} + relative{ + "-1"{""} + "0"{""} + "1"{""} + } + relativeTime{ + future{ + zero{""} + one{""} + two{""} + few{""} + many{""} + other{""} + } + past{ + zero{""} + one{""} + two{""} + few{""} + many{""} + other{""} + } + } + } + month-short{ + dn{"Month"} + relative{ + "-1"{""} + "0"{""} + "1"{""} + } + relativeTime{ + future{ + zero{""} + one{""} + two{""} + few{""} + many{""} + other{""} + } + past{ + zero{""} + one{""} + two{""} + few{""} + many{""} + other{""} + } + } + } + quarter{ + dn{""} + relative{ + "-1"{""} + "0"{""} + "1"{""} + } + relativeTime{ + future{ + zero{""} + one{""} + two{""} + few{""} + many{""} + other{""} + } + past{ + zero{""} + one{""} + two{""} + few{""} + many{""} + other{""} + } + } + } + quarter-narrow{ + dn{""} + relative{ + "-1"{""} + "0"{""} + "1"{""} + } + relativeTime{ + future{ + zero{""} + one{""} + two{""} + few{""} + many{""} + other{""} + } + past{ + zero{""} + one{""} + two{""} + few{""} + many{""} + other{""} + } + } + } + quarter-short{ + dn{""} + relative{ + "-1"{""} + "0"{""} + "1"{""} + } + relativeTime{ + future{ + zero{""} + one{""} + two{""} + few{""} + many{""} + other{""} + } + past{ + zero{""} + one{""} + two{""} + few{""} + many{""} + other{""} + } + } + } sat{ relative{ "-1"{""} @@ -4098,6 +4420,20 @@ structLocale:table(nofallback){ "1"{""} } } + sat-narrow{ + relative{ + "-1"{""} + "0"{""} + "1"{""} + } + } + sat-short{ + relative{ + "-1"{""} + "0"{""} + "1"{""} + } + } second{ dn{"Second"} relative{ @@ -4124,6 +4460,58 @@ structLocale:table(nofallback){ } } } + second-narrow{ + dn{"Second"} + relative{ + "-1"{""} + "0"{""} + "1"{""} + } + relativeTime{ + future{ + zero{""} + one{""} + two{""} + few{""} + many{""} + other{""} + } + past{ + zero{""} + one{""} + two{""} + few{""} + many{""} + other{""} + } + } + } + second-short{ + dn{"Second"} + relative{ + "-1"{""} + "0"{""} + "1"{""} + } + relativeTime{ + future{ + zero{""} + one{""} + two{""} + few{""} + many{""} + other{""} + } + past{ + zero{""} + one{""} + two{""} + few{""} + many{""} + other{""} + } + } + } sun{ relative{ "-1"{""} @@ -4131,6 +4519,20 @@ structLocale:table(nofallback){ "1"{""} } } + sun-narrow{ + relative{ + "-1"{""} + "0"{""} + "1"{""} + } + } + sun-short{ + relative{ + "-1"{""} + "0"{""} + "1"{""} + } + } thu{ relative{ "-1"{""} @@ -4138,6 +4540,20 @@ structLocale:table(nofallback){ "1"{""} } } + thu-narrow{ + relative{ + "-1"{""} + "0"{""} + "1"{""} + } + } + thu-short{ + relative{ + "-1"{""} + "0"{""} + "1"{""} + } + } tue{ relative{ "-1"{""} @@ -4145,6 +4561,20 @@ structLocale:table(nofallback){ "1"{""} } } + tue-narrow{ + relative{ + "-1"{""} + "0"{""} + "1"{""} + } + } + tue-short{ + relative{ + "-1"{""} + "0"{""} + "1"{""} + } + } wed{ relative{ "-1"{""} @@ -4152,6 +4582,20 @@ structLocale:table(nofallback){ "1"{""} } } + wed-narrow{ + relative{ + "-1"{""} + "0"{""} + "1"{""} + } + } + wed-short{ + relative{ + "-1"{""} + "0"{""} + "1"{""} + } + } week{ dn{"Week"} relative{ @@ -4178,6 +4622,58 @@ structLocale:table(nofallback){ } } } + week-narrow{ + dn{"Week"} + relative{ + "-1"{""} + "0"{""} + "1"{""} + } + relativeTime{ + future{ + zero{""} + one{""} + two{""} + few{""} + many{""} + other{""} + } + past{ + zero{""} + one{""} + two{""} + few{""} + many{""} + other{""} + } + } + } + week-short{ + dn{"Week"} + relative{ + "-1"{""} + "0"{""} + "1"{""} + } + relativeTime{ + future{ + zero{""} + one{""} + two{""} + few{""} + many{""} + other{""} + } + past{ + zero{""} + one{""} + two{""} + few{""} + many{""} + other{""} + } + } + } weekday{ dn{"Day of the Week"} relative{ @@ -4212,6 +4708,58 @@ structLocale:table(nofallback){ } } } + year-narrow{ + dn{"Year"} + relative{ + "-1"{""} + "0"{""} + "1"{""} + } + relativeTime{ + future{ + zero{""} + one{""} + two{""} + few{""} + many{""} + other{""} + } + past{ + zero{""} + one{""} + two{""} + few{""} + many{""} + other{""} + } + } + } + year-short{ + dn{"Year"} + relative{ + "-1"{""} + "0"{""} + "1"{""} + } + relativeTime{ + future{ + zero{""} + one{""} + two{""} + few{""} + many{""} + other{""} + } + past{ + zero{""} + one{""} + two{""} + few{""} + many{""} + other{""} + } + } + } zone{ dn{"Zone"} relative{