1 // © 2016 and later: Unicode, Inc. and others. 
   2 // License & terms of use: http://www.unicode.org/copyright.html 
   3 /******************************************************************** 
   4  * Copyright (c) 2008-2016, International Business Machines Corporation and 
   5  * others. All Rights Reserved. 
   6  ********************************************************************/ 
   8 #include "unicode/utypes.h" 
  10 #if !UCONFIG_NO_FORMATTING 
  12 #include "unicode/decimfmt.h" 
  13 #include "unicode/tmunit.h" 
  14 #include "unicode/tmutamt.h" 
  15 #include "unicode/tmutfmt.h" 
  16 #include "unicode/ustring.h" 
  20 //TODO: put as compilation flag 
  21 //#define TUFMTTS_DEBUG 1 
  27 class TimeUnitTest 
: public IntlTest 
{ 
  28     void runIndexedTest(int32_t index
, UBool exec
, const char* &name
, char* /*par*/ ) { 
  29         if (exec
) logln("TestSuite TimeUnitTest"); 
  31         TESTCASE_AUTO(testBasic
); 
  32         TESTCASE_AUTO(testAPI
); 
  33         TESTCASE_AUTO(testGreekWithFallback
); 
  34         TESTCASE_AUTO(testGreekWithSanitization
); 
  35         TESTCASE_AUTO(test10219Plurals
); 
  36         TESTCASE_AUTO(TestBritishShortHourFallback
); 
  42      * Performs basic tests 
  52      * Performs tests for Greek 
  53      * This tests that requests for short unit names correctly fall back  
  54      * to long unit names for a locale where the locale data does not  
  55      * provide short unit names. As of CLDR 1.9, Greek is one such language. 
  57     void testGreekWithFallback(); 
  60      * Performs tests for Greek 
  61      * This tests that if the plural count listed in time unit format does not 
  62      * match those in the plural rules for the locale, those plural count in 
  63      * time unit format will be ingored and subsequently, fall back will kick in 
  64      * which is tested above. 
  65      * Without data sanitization, setNumberFormat() would crash. 
  66      * As of CLDR shiped in ICU4.8, Greek is one such language. 
  68     void testGreekWithSanitization(); 
  71      * Performs unit test for ticket 10219 making sure that plurals work 
  72      * correctly with rounding. 
  74     void test10219Plurals(); 
  76     void TestBritishShortHourFallback(); 
  79 extern IntlTest 
*createTimeUnitTest() { 
  80     return new TimeUnitTest(); 
  83 // This function is more lenient than equals operator as it considers integer 3 hours and 
  84 // double 3.0 hours to be equal 
  85 static UBool 
tmaEqual(const TimeUnitAmount
& left
, const TimeUnitAmount
& right
) { 
  86     if (left
.getTimeUnitField() != right
.getTimeUnitField()) { 
  89     UErrorCode status 
= U_ZERO_ERROR
; 
  90     if (!left
.getNumber().isNumeric() || !right
.getNumber().isNumeric()) { 
  93     UBool result 
= left
.getNumber().getDouble(status
) == right
.getNumber().getDouble(status
); 
  94     if (U_FAILURE(status
)) { 
 103 void TimeUnitTest::testBasic() { 
 104     const char* locales
[] = {"en", "sl", "fr", "zh", "ar", "ru", "zh_Hant", "pa"}; 
 105     for ( unsigned int locIndex 
= 0;  
 106           locIndex 
< UPRV_LENGTHOF(locales
);  
 108         UErrorCode status 
= U_ZERO_ERROR
; 
 109         Locale 
loc(locales
[locIndex
]); 
 110         TimeUnitFormat
** formats 
= new TimeUnitFormat
*[2]; 
 111         formats
[UTMUTFMT_FULL_STYLE
] = new TimeUnitFormat(loc
, status
); 
 112         if (!assertSuccess("TimeUnitFormat(full)", status
, TRUE
)) return; 
 113         formats
[UTMUTFMT_ABBREVIATED_STYLE
] = new TimeUnitFormat(loc
, UTMUTFMT_ABBREVIATED_STYLE
, status
); 
 114         if (!assertSuccess("TimeUnitFormat(short)", status
)) return; 
 116         std::cout 
<< "locale: " << locales
[locIndex
] << "\n"; 
 118         for (int style 
= UTMUTFMT_FULL_STYLE
;  
 119              style 
<= UTMUTFMT_ABBREVIATED_STYLE
; 
 121           for (TimeUnit::UTimeUnitFields j 
= TimeUnit::UTIMEUNIT_YEAR
;  
 122              j 
< TimeUnit::UTIMEUNIT_FIELD_COUNT
;  
 123              j 
= (TimeUnit::UTimeUnitFields
)(j
+1)) { 
 125             std::cout 
<< "time unit: " << j 
<< "\n"; 
 127             double tests
[] = {0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 5, 10, 100, 101.35}; 
 128             for (unsigned int i 
= 0; i 
< UPRV_LENGTHOF(tests
); ++i
) { 
 130                 std::cout 
<< "number: " << tests
[i
] << "\n"; 
 132                 TimeUnitAmount
* source 
= new TimeUnitAmount(tests
[i
], j
, status
); 
 133                 if (!assertSuccess("TimeUnitAmount()", status
)) return; 
 134                 UnicodeString formatted
; 
 135                 Formattable formattable
; 
 136                 formattable
.adoptObject(source
); 
 137                 formatted 
= ((Format
*)formats
[style
])->format(formattable
, formatted
, status
); 
 138                 if (!assertSuccess("format()", status
)) return; 
 140                 char formatResult
[1000]; 
 141                 formatted
.extract(0, formatted
.length(), formatResult
, "UTF-8"); 
 142                 std::cout 
<< "format result: " << formatResult 
<< "\n"; 
 145                 ((Format
*)formats
[style
])->parseObject(formatted
, result
, status
); 
 146                 if (!assertSuccess("parseObject()", status
)) return; 
 147                 if (!tmaEqual(*((TimeUnitAmount 
*)result
.getObject()), *((TimeUnitAmount 
*) formattable
.getObject()))) { 
 148                     dataerrln("No round trip: "); 
 150                 // other style parsing 
 151                 Formattable result_1
; 
 152                 ((Format
*)formats
[1-style
])->parseObject(formatted
, result_1
, status
); 
 153                 if (!assertSuccess("parseObject()", status
)) return; 
 154                 if (!tmaEqual(*((TimeUnitAmount 
*)result_1
.getObject()), *((TimeUnitAmount 
*) formattable
.getObject()))) { 
 155                     dataerrln("No round trip: "); 
 160         delete formats
[UTMUTFMT_FULL_STYLE
]; 
 161         delete formats
[UTMUTFMT_ABBREVIATED_STYLE
]; 
 167 void TimeUnitTest::testAPI() { 
 168     //================= TimeUnit ================= 
 169     UErrorCode status 
= U_ZERO_ERROR
; 
 171     TimeUnit
* tmunit 
= TimeUnit::createInstance(TimeUnit::UTIMEUNIT_YEAR
, status
); 
 172     if (!assertSuccess("TimeUnit::createInstance", status
)) return; 
 174     TimeUnit
* another 
= tmunit
->clone(); 
 175     TimeUnit 
third(*tmunit
); 
 176     TimeUnit fourth 
= third
; 
 178     assertTrue("orig and clone are equal", (*tmunit 
== *another
)); 
 179     assertTrue("copied and assigned are equal", (third 
== fourth
)); 
 181     TimeUnit
* tmunit_m 
= TimeUnit::createInstance(TimeUnit::UTIMEUNIT_MONTH
, status
); 
 182     assertTrue("year != month", (*tmunit 
!= *tmunit_m
)); 
 184     TimeUnit::UTimeUnitFields field 
= tmunit_m
->getTimeUnitField(); 
 185     assertTrue("field of month time unit is month", (field 
== TimeUnit::UTIMEUNIT_MONTH
)); 
 187     //===== Interoperability with MeasureUnit ====== 
 188     MeasureUnit 
**ptrs 
= new MeasureUnit 
*[TimeUnit::UTIMEUNIT_FIELD_COUNT
]; 
 190     ptrs
[TimeUnit::UTIMEUNIT_YEAR
] = MeasureUnit::createYear(status
); 
 191     ptrs
[TimeUnit::UTIMEUNIT_MONTH
] = MeasureUnit::createMonth(status
); 
 192     ptrs
[TimeUnit::UTIMEUNIT_DAY
] = MeasureUnit::createDay(status
); 
 193     ptrs
[TimeUnit::UTIMEUNIT_WEEK
] = MeasureUnit::createWeek(status
); 
 194     ptrs
[TimeUnit::UTIMEUNIT_HOUR
] = MeasureUnit::createHour(status
); 
 195     ptrs
[TimeUnit::UTIMEUNIT_MINUTE
] = MeasureUnit::createMinute(status
); 
 196     ptrs
[TimeUnit::UTIMEUNIT_SECOND
] = MeasureUnit::createSecond(status
); 
 197     if (!assertSuccess("TimeUnit::createInstance", status
)) return; 
 199     for (TimeUnit::UTimeUnitFields j 
= TimeUnit::UTIMEUNIT_YEAR
;  
 200             j 
< TimeUnit::UTIMEUNIT_FIELD_COUNT
;  
 201             j 
= (TimeUnit::UTimeUnitFields
)(j
+1)) { 
 202         MeasureUnit 
*ptr 
= TimeUnit::createInstance(j
, status
); 
 203         if (!assertSuccess("TimeUnit::createInstance", status
)) return; 
 204         // We have to convert *ptr to a MeasureUnit or else == will fail over 
 205         // differing types (TimeUnit vs. MeasureUnit). 
 207                 "Time unit should be equal to corresponding MeasureUnit", 
 208                 MeasureUnit(*ptr
) == *ptrs
[j
]); 
 214     for (int i 
= 0; i 
< TimeUnit::UTIMEUNIT_FIELD_COUNT
; ++i
) { 
 220     //================= TimeUnitAmount ================= 
 222     Formattable 
formattable((int32_t)2); 
 223     TimeUnitAmount 
tma_long(formattable
, TimeUnit::UTIMEUNIT_DAY
, status
); 
 224     if (!assertSuccess("TimeUnitAmount(formattable...)", status
)) return; 
 226     formattable
.setDouble(2); 
 227     TimeUnitAmount 
tma_double(formattable
, TimeUnit::UTIMEUNIT_DAY
, status
); 
 228     if (!assertSuccess("TimeUnitAmount(formattable...)", status
)) return; 
 230     formattable
.setDouble(3); 
 231     TimeUnitAmount 
tma_double_3(formattable
, TimeUnit::UTIMEUNIT_DAY
, status
); 
 232     if (!assertSuccess("TimeUnitAmount(formattable...)", status
)) return; 
 234     TimeUnitAmount 
tma(2, TimeUnit::UTIMEUNIT_DAY
, status
); 
 235     if (!assertSuccess("TimeUnitAmount(number...)", status
)) return; 
 237     TimeUnitAmount 
tma_h(2, TimeUnit::UTIMEUNIT_HOUR
, status
); 
 238     if (!assertSuccess("TimeUnitAmount(number...)", status
)) return; 
 240     TimeUnitAmount 
second(tma
); 
 241     TimeUnitAmount third_tma 
= tma
; 
 242     TimeUnitAmount
* fourth_tma 
= tma
.clone(); 
 244     assertTrue("orig and copy are equal", (second 
== tma
)); 
 245     assertTrue("clone and assigned are equal", (third_tma 
== *fourth_tma
)); 
 246     assertTrue("different if number diff", (tma_double 
!= tma_double_3
)); 
 247     assertTrue("different if number type diff", (tma_double 
!= tma_long
)); 
 248     assertTrue("different if time unit diff", (tma 
!= tma_h
)); 
 249     assertTrue("same even different constructor", (tma_double 
== tma
)); 
 251     assertTrue("getTimeUnitField", (tma
.getTimeUnitField() == TimeUnit::UTIMEUNIT_DAY
)); 
 254     //================= TimeUnitFormat ================= 
 256     TimeUnitFormat
* tmf_en 
= new TimeUnitFormat(Locale("en"), status
); 
 257     if (!assertSuccess("TimeUnitFormat(en...)", status
, TRUE
)) return; 
 258     TimeUnitFormat 
tmf_fr(Locale("fr"), status
); 
 259     if (!assertSuccess("TimeUnitFormat(fr...)", status
)) return; 
 261     assertTrue("TimeUnitFormat: en and fr diff", (*tmf_en 
!= tmf_fr
)); 
 263     TimeUnitFormat tmf_assign 
= *tmf_en
; 
 264     assertTrue("TimeUnitFormat: orig and assign are equal", (*tmf_en 
== tmf_assign
)); 
 266     TimeUnitFormat 
tmf_copy(tmf_fr
); 
 267     assertTrue("TimeUnitFormat: orig and copy are equal", (tmf_fr 
== tmf_copy
)); 
 269     TimeUnitFormat
* tmf_clone 
= tmf_en
->clone(); 
 270     assertTrue("TimeUnitFormat: orig and clone are equal", (*tmf_en 
== *tmf_clone
)); 
 273     tmf_en
->setLocale(Locale("fr"), status
); 
 274     if (!assertSuccess("setLocale(fr...)", status
)) return; 
 276     NumberFormat
* numberFmt 
= NumberFormat::createInstance( 
 277                                  Locale("fr"), status
); 
 278     if (!assertSuccess("NumberFormat::createInstance()", status
)) return; 
 279     tmf_en
->setNumberFormat(*numberFmt
, status
); 
 280     if (!assertSuccess("setNumberFormat(en...)", status
)) return; 
 281     assertTrue("TimeUnitFormat: setLocale", (*tmf_en 
== tmf_fr
)); 
 285     TimeUnitFormat
* en_long 
= new TimeUnitFormat(Locale("en"), UTMUTFMT_FULL_STYLE
, status
); 
 286     if (!assertSuccess("TimeUnitFormat(en...)", status
)) return; 
 289     TimeUnitFormat
* en_short 
= new TimeUnitFormat(Locale("en"), UTMUTFMT_ABBREVIATED_STYLE
, status
); 
 290     if (!assertSuccess("TimeUnitFormat(en...)", status
)) return; 
 293     TimeUnitFormat
* format 
= new TimeUnitFormat(status
); 
 294     format
->setLocale(Locale("zh"), status
); 
 295     format
->setNumberFormat(*numberFmt
, status
); 
 296     if (!assertSuccess("TimeUnitFormat(en...)", status
)) return; 
 302  * Tests for Greek Language. 
 303  * This tests that requests for short unit names correctly fall back  
 304  * to long unit names for a locale where the locale data does not  
 305  * provide short unit names. As of CLDR 1.9, Greek is one such language. 
 307 void TimeUnitTest::testGreekWithFallback() { 
 308     UErrorCode status 
= U_ZERO_ERROR
; 
 310     const char* locales
[] = {"el-GR", "el"}; 
 311     TimeUnit::UTimeUnitFields tunits
[] = {TimeUnit::UTIMEUNIT_SECOND
, TimeUnit::UTIMEUNIT_MINUTE
, TimeUnit::UTIMEUNIT_HOUR
, TimeUnit::UTIMEUNIT_DAY
, TimeUnit::UTIMEUNIT_MONTH
, TimeUnit::UTIMEUNIT_YEAR
}; 
 312     UTimeUnitFormatStyle styles
[] = {UTMUTFMT_FULL_STYLE
, UTMUTFMT_ABBREVIATED_STYLE
}; 
 313     const int numbers
[] = {1, 7}; 
 315     const UChar oneSecond
[] = {0x0031, 0x0020, 0x03b4, 0x03b5, 0x03c5, 0x03c4, 0x03b5, 0x03c1, 0x03cc, 0x03bb, 0x03b5, 0x03c0, 0x03c4, 0x03bf, 0}; 
 316     const UChar oneSecondShort
[] = {0x0031, 0x0020, 0x03b4, 0x03b5, 0x03c5, 0x03c4, 0x002e, 0}; 
 317     const UChar oneMinute
[] = {0x0031, 0x0020, 0x03bb, 0x03b5, 0x03c0, 0x03c4, 0x03cc, 0}; 
 318     const UChar oneMinuteShort
[] = {0x0031, 0x0020, 0x03bb, 0x03b5, 0x03c0, 0x002e, 0}; 
 319     const UChar oneHour
[] = {0x0031, 0x0020, 0x03ce, 0x03c1, 0x03b1, 0}; 
 320     const UChar oneDay
[] = {0x0031, 0x0020, 0x03b7, 0x03bc, 0x03ad, 0x03c1, 0x03b1, 0}; 
 321     const UChar oneMonth
[] = {0x0031, 0x0020, 0x03bc, 0x03ae, 0x03bd, 0x03b1, 0x03c2, 0}; 
 322     const UChar oneMonthShort
[] = {0x0031, 0x0020, 0x03bc, 0x03ae, 0x03bd, 0x002e, 0}; 
 323     const UChar oneYear
[] = {0x0031, 0x0020, 0x03ad, 0x03c4, 0x03bf, 0x03c2, 0}; 
 324     const UChar oneYearShort
[] = {0x0031, 0x0020, 0x03ad, 0x03c4, 0x002e, 0}; 
 325     const UChar sevenSeconds
[] = {0x0037, 0x0020, 0x03b4, 0x03b5, 0x03c5, 0x03c4, 0x03b5, 0x03c1, 0x03cc, 0x03bb, 0x03b5, 0x03c0, 0x03c4, 0x03b1, 0}; 
 326     const UChar sevenSecondsShort
[] = {0x0037, 0x0020, 0x03b4, 0x03b5, 0x03c5, 0x03c4, 0x002e, 0}; 
 327     const UChar sevenMinutes
[] = {0x0037, 0x0020, 0x03bb, 0x03b5, 0x03c0, 0x03c4, 0x03ac, 0}; 
 328     const UChar sevenMinutesShort
[] = {0x0037, 0x0020, 0x03bb, 0x03b5, 0x03c0, 0x002e, 0}; 
 329     const UChar sevenHours
[] = {0x0037, 0x0020, 0x03ce, 0x03c1, 0x03b5, 0x03c2, 0}; 
 330     const UChar sevenHoursShort
[] = {0x0037, 0x0020, 0x03ce, 0x03c1, 0x002e, 0}; 
 331     const UChar sevenDays
[] = {0x0037, 0x0020, 0x03b7, 0x03bc, 0x03ad, 0x03c1, 0x03b5, 0x03c2, 0}; 
 332     const UChar sevenMonths
[] = {0x0037, 0x0020, 0x03bc, 0x03ae, 0x03bd, 0x03b5, 0x3c2, 0}; 
 333     const UChar sevenMonthsShort
[] = {0x0037, 0x0020, 0x03bc, 0x03ae, 0x03bd, 0x002e, 0}; 
 334     const UChar sevenYears
[] = {0x0037, 0x0020, 0x03ad, 0x03c4, 0x03b7, 0}; 
 335     const UChar sevenYearsShort
[] = {0x0037, 0x0020, 0x03ad, 0x03c4, 0x002e, 0}; 
 337     const UnicodeString 
oneSecondStr(oneSecond
); 
 338     const UnicodeString 
oneSecondShortStr(oneSecondShort
); 
 339     const UnicodeString 
oneMinuteStr(oneMinute
); 
 340     const UnicodeString 
oneMinuteShortStr(oneMinuteShort
); 
 341     const UnicodeString 
oneHourStr(oneHour
); 
 342     const UnicodeString 
oneDayStr(oneDay
); 
 343     const UnicodeString 
oneMonthStr(oneMonth
); 
 344     const UnicodeString 
oneMonthShortStr(oneMonthShort
); 
 345     const UnicodeString 
oneYearStr(oneYear
); 
 346     const UnicodeString 
oneYearShortStr(oneYearShort
); 
 347     const UnicodeString 
sevenSecondsStr(sevenSeconds
); 
 348     const UnicodeString 
sevenSecondsShortStr(sevenSecondsShort
); 
 349     const UnicodeString 
sevenMinutesStr(sevenMinutes
); 
 350     const UnicodeString 
sevenMinutesShortStr(sevenMinutesShort
); 
 351     const UnicodeString 
sevenHoursStr(sevenHours
); 
 352     const UnicodeString 
sevenHoursShortStr(sevenHoursShort
); 
 353     const UnicodeString 
sevenDaysStr(sevenDays
); 
 354     const UnicodeString 
sevenMonthsStr(sevenMonths
); 
 355     const UnicodeString 
sevenMonthsShortStr(sevenMonthsShort
); 
 356     const UnicodeString 
sevenYearsStr(sevenYears
); 
 357     const UnicodeString 
sevenYearsShortStr(sevenYearsShort
); 
 359     const UnicodeString expected
[] = { 
 360             oneSecondStr
, oneMinuteStr
, oneHourStr
, oneDayStr
, oneMonthStr
, oneYearStr
, 
 361             oneSecondShortStr
, oneMinuteShortStr
, oneHourStr
, oneDayStr
, oneMonthShortStr
, oneYearShortStr
, 
 362             sevenSecondsStr
, sevenMinutesStr
, sevenHoursStr
, sevenDaysStr
, sevenMonthsStr
, sevenYearsStr
, 
 363             sevenSecondsShortStr
, sevenMinutesShortStr
, sevenHoursShortStr
, sevenDaysStr
, sevenMonthsShortStr
, sevenYearsShortStr
, 
 365             oneSecondStr
, oneMinuteStr
, oneHourStr
, oneDayStr
, oneMonthStr
, oneYearStr
, 
 366             oneSecondShortStr
, oneMinuteShortStr
, oneHourStr
, oneDayStr
, oneMonthShortStr
, oneYearShortStr
, 
 367             sevenSecondsStr
, sevenMinutesStr
, sevenHoursStr
, sevenDaysStr
, sevenMonthsStr
, sevenYearsStr
, 
 368             sevenSecondsShortStr
, sevenMinutesShortStr
, sevenHoursShortStr
, sevenDaysStr
, sevenMonthsShortStr
, sevenYearsShortStr
}; 
 371     for ( unsigned int locIndex 
= 0; 
 372         locIndex 
< UPRV_LENGTHOF(locales
); 
 375         Locale l 
= Locale::createFromName(locales
[locIndex
]); 
 377         for ( unsigned int numberIndex 
= 0; 
 378             numberIndex 
< UPRV_LENGTHOF(numbers
); 
 381             for ( unsigned int styleIndex 
= 0; 
 382                 styleIndex 
< UPRV_LENGTHOF(styles
); 
 385                 for ( unsigned int unitIndex 
= 0; 
 386                     unitIndex 
< UPRV_LENGTHOF(tunits
); 
 389                     LocalPointer
<TimeUnitAmount
>tamt(new TimeUnitAmount(numbers
[numberIndex
], tunits
[unitIndex
], status
)); 
 390                     if (U_FAILURE(status
)) { 
 391                         dataerrln("generating TimeUnitAmount Object failed."); 
 393                         std::cout 
<< "Failed to get TimeUnitAmount for " << tunits
[unitIndex
] << "\n"; 
 398                     LocalPointer
<TimeUnitFormat
> tfmt(new TimeUnitFormat(l
, styles
[styleIndex
], status
)); 
 399                     if (U_FAILURE(status
)) { 
 400                         dataerrln("generating TimeUnitAmount Object failed."); 
 402                        std::cout 
<<  "Failed to get TimeUnitFormat for " << locales
[locIndex
] << "\n"; 
 410                     fmt
.adoptObject(tamt
.orphan()); 
 411                     str 
= ((Format 
*)tfmt
.getAlias())->format(fmt
, str
, status
); 
 412                     if (!assertSuccess("formatting relative time failed", status
)) { 
 414                         std::cout 
<<  "Failed to format" << "\n"; 
 420                     char tmp
[128];    //output 
 421                     char tmp1
[128];    //expected 
 423                     u_strToUTF8(tmp
, 128, &len
, str
.getTerminatedBuffer(), str
.length(), &status
); 
 424                     u_strToUTF8(tmp1
, 128, &len
, expected
[counter
].unescape().getTerminatedBuffer(), expected
[counter
].unescape().length(), &status
); 
 425                     std::cout 
<<  "Formatted string : " << tmp 
<< " expected : " << tmp1 
<< "\n"; 
 427                     if (!assertEquals("formatted time string is not expected, locale: " + UnicodeString(locales
[locIndex
]) + " style: " + (int)styles
[styleIndex
] + " units: " + (int)tunits
[unitIndex
], expected
[counter
], str
)) { 
 440 void TimeUnitTest::testGreekWithSanitization() { 
 442     UErrorCode status 
= U_ZERO_ERROR
; 
 444     NumberFormat
* numberFmt 
= NumberFormat::createInstance(Locale("el"), status
); 
 445     if (!assertSuccess("NumberFormat::createInstance for el locale", status
, TRUE
)) return; 
 446     numberFmt
->setMaximumFractionDigits(1); 
 448     TimeUnitFormat
* timeUnitFormat 
= new TimeUnitFormat(elLoc
, status
); 
 449     if (!assertSuccess("TimeUnitFormat::TimeUnitFormat for el locale", status
)) return; 
 451     timeUnitFormat
->setNumberFormat(*numberFmt
, status
); 
 454     delete timeUnitFormat
; 
 457 void TimeUnitTest::test10219Plurals() { 
 458     Locale 
usLocale("en_US"); 
 459     double values
[2] = {1.588, 1.011}; 
 460     UnicodeString expected
[2][3] = { 
 461         {"1 minute", "1.5 minutes", "1.58 minutes"}, 
 462         {"1 minute", "1.0 minutes", "1.01 minutes"} 
 464     UErrorCode status 
= U_ZERO_ERROR
; 
 465     TimeUnitFormat 
tuf(usLocale
, status
); 
 466     if (U_FAILURE(status
)) { 
 467         dataerrln("generating TimeUnitFormat Object failed: %s", u_errorName(status
)); 
 470     LocalPointer
<DecimalFormat
> nf((DecimalFormat 
*) NumberFormat::createInstance(usLocale
, status
)); 
 471     if (U_FAILURE(status
)) { 
 472         dataerrln("generating NumberFormat Object failed: %s", u_errorName(status
)); 
 475     for (int32_t j 
= 0; j 
< UPRV_LENGTHOF(values
); ++j
) { 
 476         for (int32_t i 
= 0; i 
< UPRV_LENGTHOF(expected
[j
]); ++i
) { 
 477             nf
->setMinimumFractionDigits(i
); 
 478             nf
->setMaximumFractionDigits(i
); 
 479             nf
->setRoundingMode(DecimalFormat::kRoundDown
); 
 480             tuf
.setNumberFormat(*nf
, status
); 
 481             if (U_FAILURE(status
)) { 
 482                 dataerrln("setting NumberFormat failed: %s", u_errorName(status
)); 
 485             UnicodeString actual
; 
 487             LocalPointer
<TimeUnitAmount
> tamt( 
 488                 new TimeUnitAmount(values
[j
], TimeUnit::UTIMEUNIT_MINUTE
, status
), status
); 
 489             if (U_FAILURE(status
)) { 
 490                 dataerrln("generating TimeUnitAmount Object failed: %s", u_errorName(status
)); 
 493             fmt
.adoptObject(tamt
.orphan()); 
 494             tuf
.format(fmt
, actual
, status
); 
 495             if (U_FAILURE(status
)) { 
 496                 dataerrln("Actual formatting failed: %s", u_errorName(status
)); 
 499             if (expected
[j
][i
] != actual
) { 
 500                 errln("Expected " + expected
[j
][i
] + ", got " + actual
); 
 508     UnicodeString formattedString 
= "1 minutes"; 
 509     tuf
.parseObject(formattedString
, result
, pos
); 
 510     if (formattedString
.length() != pos
.getIndex()) { 
 511         errln("Expect parsing to go all the way to the end of the string."); 
 515 void TimeUnitTest::TestBritishShortHourFallback() { 
 516     // See ticket #11986 "incomplete fallback in MeasureFormat". 
 517     UErrorCode status 
= U_ZERO_ERROR
; 
 518     Formattable 
oneHour(new TimeUnitAmount(1, TimeUnit::UTIMEUNIT_HOUR
, status
)); 
 519     Locale 
en_GB("en_GB"); 
 520     TimeUnitFormat 
formatter(en_GB
, UTMUTFMT_ABBREVIATED_STYLE
, status
); 
 521     UnicodeString result
; 
 522     formatter
.format(oneHour
, result
, status
); 
 523     assertSuccess("TestBritishShortHourFallback()", status
); 
 524     assertEquals("TestBritishShortHourFallback()", UNICODE_STRING_SIMPLE("1 hr"), result
, TRUE
);