Home | History | Annotate | Download | only in format
      1 //  2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html#License
      3 /*
      4  *******************************************************************************
      5  * Copyright (C) 2008-2015, International Business Machines Corporation and
      6  * others. All Rights Reserved.
      7  *******************************************************************************
      8  */
      9 package com.ibm.icu.dev.test.format;
     10 
     11 import java.text.ParseException;
     12 import java.text.ParsePosition;
     13 import java.util.Locale;
     14 
     15 import org.junit.Test;
     16 import org.junit.runner.RunWith;
     17 import org.junit.runners.JUnit4;
     18 
     19 import com.ibm.icu.dev.test.TestFmwk;
     20 import com.ibm.icu.math.BigDecimal;
     21 import com.ibm.icu.text.MeasureFormat;
     22 import com.ibm.icu.text.NumberFormat;
     23 import com.ibm.icu.text.TimeUnitFormat;
     24 import com.ibm.icu.util.Measure;
     25 import com.ibm.icu.util.MeasureUnit;
     26 import com.ibm.icu.util.TimeUnit;
     27 import com.ibm.icu.util.TimeUnitAmount;
     28 import com.ibm.icu.util.ULocale;
     29 
     30 /**
     31  * @author markdavis
     32  *
     33  */
     34 @RunWith(JUnit4.class)
     35 public class TimeUnitTest extends TestFmwk {
     36     @Test
     37     public void Test10219FractionalPlurals() {
     38         TimeUnitFormat tuf = new TimeUnitFormat(ULocale.ENGLISH, TimeUnitFormat.FULL_NAME);
     39         String[] expected = {"1 minute", "1.5 minutes", "1.58 minutes"};
     40         for (int i = 2; i >= 0; i--) {
     41             NumberFormat nf = NumberFormat.getNumberInstance(ULocale.ENGLISH);
     42             nf.setRoundingMode(BigDecimal.ROUND_DOWN);
     43             nf.setMaximumFractionDigits(i);
     44             tuf.setNumberFormat(nf);
     45             assertEquals("Test10219", expected[i], tuf.format(new TimeUnitAmount(1.588, TimeUnit.MINUTE)));
     46         }
     47     }
     48 
     49     @Test
     50     public void Test10219FactionalPluralsParse() throws ParseException {
     51         TimeUnitFormat tuf = new TimeUnitFormat(ULocale.ENGLISH, TimeUnitFormat.FULL_NAME);
     52         ParsePosition ppos = new ParsePosition(0);
     53         String parseString = "1 minutes";
     54         tuf.parseObject(parseString, ppos);
     55 
     56         // Parsing should go all the way to the end of the string.
     57         // We want the longest match, and we don't care if the plural form of the unit
     58         // matches the plural form of the number.
     59         assertEquals("Test10219FractionalPluralParse", parseString.length(), ppos.getIndex());
     60     }
     61 
     62     @Test
     63     public void TestBasic() {
     64         String[] locales = {"en", "sl", "fr", "zh", "ar", "ru", "zh_Hant"};
     65         for ( int locIndex = 0; locIndex < locales.length; ++locIndex ) {
     66             //System.out.println("locale: " + locales[locIndex]);
     67             TimeUnitFormat[] formats = new TimeUnitFormat[] {
     68                 new TimeUnitFormat(new ULocale(locales[locIndex]), TimeUnitFormat.FULL_NAME),
     69                 new TimeUnitFormat(new ULocale(locales[locIndex]), TimeUnitFormat.ABBREVIATED_NAME),
     70 
     71             };
     72             for (int style = TimeUnitFormat.FULL_NAME;
     73                  style <= TimeUnitFormat.ABBREVIATED_NAME;
     74                  ++style) {
     75                 final TimeUnit[] values = TimeUnit.values();
     76                 for (int j = 0; j < values.length; ++j) {
     77                     final TimeUnit timeUnit = values[j];
     78                     double[] tests = {0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 5, 10, 100, 101.35};
     79                     for (int i = 0; i < tests.length; ++i) {
     80                         TimeUnitAmount source = new TimeUnitAmount(tests[i], timeUnit);
     81                         String formatted = formats[style].format(source);
     82                         //System.out.println(formatted);
     83                         logln(tests[i] + " => " + formatted);
     84                         try {
     85                             // Style should not matter when parsing.
     86                             for (int parseStyle = TimeUnitFormat.FULL_NAME; parseStyle <= TimeUnitFormat.ABBREVIATED_NAME; parseStyle++) {
     87                                 TimeUnitAmount result = (TimeUnitAmount) formats[parseStyle].parseObject(formatted);
     88                                 if (result == null || !source.equals(result)) {
     89                                     errln("No round trip: " + source + " => " + formatted + " => " + result);
     90                                 }
     91                             }
     92                         } catch (ParseException e) {
     93                             errln(e.getMessage());
     94                         }
     95                     }
     96                 }
     97             }
     98         }
     99     }
    100 
    101     @Test
    102     public void TestAPI() {
    103         TimeUnitFormat format = new TimeUnitFormat();
    104         format.setLocale(new ULocale("pt_BR"));
    105         formatParsing(format);
    106         format = new TimeUnitFormat(new ULocale("de"));
    107         formatParsing(format);
    108         format = new TimeUnitFormat(new ULocale("ja"));
    109         format.setNumberFormat(NumberFormat.getNumberInstance(new ULocale("en")));
    110         formatParsing(format);
    111 
    112         format = new TimeUnitFormat();
    113         ULocale es = new ULocale("es");
    114         format.setNumberFormat(NumberFormat.getNumberInstance(es));
    115         format.setLocale(es);
    116         formatParsing(format);
    117 
    118         format.setLocale(new Locale("pt_BR"));
    119         formatParsing(format);
    120         format = new TimeUnitFormat(new Locale("de"));
    121         formatParsing(format);
    122         format = new TimeUnitFormat(new Locale("ja"));
    123         format.setNumberFormat(NumberFormat.getNumberInstance(new Locale("en")));
    124         formatParsing(format);
    125     }
    126 
    127     @Test
    128     public void TestClone() {
    129         TimeUnitFormat tuf = new TimeUnitFormat(ULocale.ENGLISH, TimeUnitFormat.ABBREVIATED_NAME);
    130         NumberFormat nf = NumberFormat.getInstance();
    131         tuf.setNumberFormat(nf);
    132         TimeUnitFormat tufClone = (TimeUnitFormat) tuf.clone();
    133         tuf.setLocale(Locale.GERMAN);
    134         assertEquals("", "1 hr", tufClone.format(new TimeUnitAmount(1, TimeUnit.HOUR)));
    135     }
    136 
    137     @Test
    138     public void TestEqHashCode() {
    139         TimeUnitFormat tf = new TimeUnitFormat(ULocale.ENGLISH, TimeUnitFormat.FULL_NAME);
    140         MeasureFormat tfeq = new TimeUnitFormat(ULocale.ENGLISH, TimeUnitFormat.FULL_NAME);
    141 
    142         MeasureFormat tfne = new TimeUnitFormat(ULocale.ENGLISH, TimeUnitFormat.ABBREVIATED_NAME);
    143         MeasureFormat tfne2 = new TimeUnitFormat(ULocale.GERMAN, TimeUnitFormat.FULL_NAME);
    144         verifyEqualsHashCode(tf, tfeq, tfne);
    145         verifyEqualsHashCode(tf, tfeq, tfne2);
    146     }
    147 
    148     @Test
    149     public void TestGetLocale() {
    150         TimeUnitFormat tf = new TimeUnitFormat(ULocale.GERMAN);
    151         assertEquals("", ULocale.GERMAN, tf.getLocale(ULocale.VALID_LOCALE));
    152     }
    153 
    154     /*
    155      * @bug 7902
    156      * This tests that requests for short unit names correctly fall back
    157      * to long unit names for a locale where the locale data does not
    158      * provide short unit names. As of CLDR 1.9, Greek is one such language.
    159      */
    160     @Test
    161     public void TestGreek() {
    162         String[] locales = {"el_GR", "el"};
    163         final TimeUnit[] units = new TimeUnit[]{
    164                 TimeUnit.SECOND,
    165                 TimeUnit.MINUTE,
    166                 TimeUnit.HOUR,
    167                 TimeUnit.DAY,
    168                 TimeUnit.WEEK,
    169                 TimeUnit.MONTH,
    170                 TimeUnit.YEAR};
    171         int[] styles = new int[] {TimeUnitFormat.FULL_NAME, TimeUnitFormat.ABBREVIATED_NAME};
    172         int[] numbers = new int[] {1, 7};
    173 
    174         String[] expected = {
    175                 // "el_GR" 1 wide
    176                 "1 ",
    177                 "1 ",
    178                 "1 ",
    179                 "1 ",
    180                 "1 ",
    181                 "1 ",
    182                 "1 ",
    183                 // "el_GR" 1 short
    184                 "1 .",
    185                 "1 .",
    186                 "1 ",
    187                 "1 ",
    188                 "1 .",
    189                 "1 .",
    190                 "1 .",	        // year (one)
    191                 // "el_GR" 7 wide
    192                 "7 ",
    193                 "7 ",
    194                 "7 ",
    195                 "7 ",
    196                 "7 ",
    197                 "7 ",
    198                 "7 ",
    199                 // "el_GR" 7 short
    200                 "7 .",
    201                 "7 .",
    202                 "7 .",		    // hour (other)
    203                 "7 ",
    204                 "7 .",
    205                 "7 .",
    206                 "7 .",            // year (other)
    207                 // "el" 1 wide
    208                 "1 ",
    209                 "1 ",
    210                 "1 ",
    211                 "1 ",
    212                 "1 ",
    213                 "1 ",
    214                 "1 ",
    215                 // "el" 1 short
    216                 "1 .",
    217                 "1 .",
    218                 "1 ",
    219                 "1 ",
    220                 "1 .",
    221                 "1 .",
    222                 "1 .",	        // year (one)
    223                 // "el" 7 wide
    224                 "7 ",
    225                 "7 ",
    226                 "7 ",
    227                 "7 ",
    228                 "7 ",
    229                 "7 ",
    230                 "7 ",
    231                 // "el" 7 short
    232                 "7 .",
    233                 "7 .",
    234                 "7 .",		    // hour (other)
    235                 "7 ",
    236                 "7 .",
    237                 "7 .",
    238                 "7 ."};           // year (other
    239 
    240         int counter = 0;
    241         TimeUnitFormat timeUnitFormat;
    242         TimeUnitAmount timeUnitAmount;
    243         String formatted;
    244 
    245         for ( int locIndex = 0; locIndex < locales.length; ++locIndex ) {
    246             for( int numIndex = 0; numIndex < numbers.length; ++numIndex ) {
    247                 for ( int styleIndex = 0; styleIndex < styles.length; ++styleIndex ) {
    248                     for ( int unitIndex = 0; unitIndex < units.length; ++unitIndex ) {
    249 
    250                         timeUnitAmount = new TimeUnitAmount(numbers[numIndex], units[unitIndex]);
    251                         timeUnitFormat = new TimeUnitFormat(new ULocale(locales[locIndex]), styles[styleIndex]);
    252                         formatted = timeUnitFormat.format(timeUnitAmount);
    253 
    254                         assertEquals(
    255                                 "locale: " + locales[locIndex]
    256                                         + ", style: " + styles[styleIndex]
    257                                                 + ", units: " + units[unitIndex]
    258                                                         + ", value: " + numbers[numIndex],
    259                                                 expected[counter], formatted);
    260                         ++counter;
    261                     }
    262                 }
    263             }
    264         }
    265     }
    266 
    267     /**
    268      * @bug9042
    269      * Performs tests for Greek.
    270      * This tests that if the plural count listed in time unit format does not
    271      * match those in the plural rules for the locale, those plural count in
    272      * time unit format will be ingored and subsequently, fall back will kick in
    273      * which is tested above.
    274      * Without data sanitization, setNumberFormat() would crash.
    275      * As of CLDR shiped in ICU4.8, Greek is one such language.
    276      */
    277     @Test
    278     public void TestGreekWithSanitization() {
    279         ULocale loc = new ULocale("el");
    280         NumberFormat numfmt = NumberFormat.getInstance(loc);
    281         TimeUnitFormat tuf = new TimeUnitFormat(loc);
    282         tuf.parseObject("", new ParsePosition(0));
    283         tuf.setNumberFormat(numfmt);
    284     }
    285 
    286     @Test
    287     public void TestBritishShortHourFallback() {
    288         // See ticket #11986 "incomplete fallback in MeasureFormat".
    289         Object oneHour = new TimeUnitAmount(1, TimeUnit.HOUR);
    290         ULocale en_GB = new ULocale("en_GB");
    291         TimeUnitFormat formatter = new TimeUnitFormat(en_GB, TimeUnitFormat.ABBREVIATED_NAME);
    292         String result = formatter.format(oneHour);
    293         assertEquals("TestBritishShortHourFallback()", "1 hr", result);
    294 
    295         // Check that we can load the time unit formatting data for all locales.
    296         for (ULocale locale : ULocale.getAvailableLocales()) {
    297             try {
    298                 new TimeUnitFormat(locale, TimeUnitFormat.ABBREVIATED_NAME);
    299             } catch (RuntimeException e) {
    300                 errln("failed to load TimeUnitFormat data for " + locale + ": " + e);
    301             }
    302         }
    303     }
    304 
    305     private void formatParsing(TimeUnitFormat format) {
    306         final TimeUnit[] values = TimeUnit.values();
    307         for (int j = 0; j < values.length; ++j) {
    308             final TimeUnit timeUnit = values[j];
    309             double[] tests = {0, 0.5, 1, 2, 3, 5};
    310             for (int i = 0; i < tests.length; ++i) {
    311                 TimeUnitAmount source = new TimeUnitAmount(tests[i], timeUnit);
    312                 String formatted = format.format(source);
    313                 //System.out.println(formatted);
    314                 logln(tests[i] + " => " + formatted);
    315                 try {
    316                     TimeUnitAmount result = (TimeUnitAmount) format.parseObject(formatted);
    317                     if (result == null || !source.equals(result)) {
    318                         errln("No round trip: " + source + " => " + formatted + " => " + result);
    319                     }
    320                 } catch (ParseException e) {
    321                     errln(e.getMessage());
    322                 }
    323             }
    324         }
    325     }
    326 
    327     /*
    328      * Tests the method public TimeUnitFormat(ULocale locale, int style), public TimeUnitFormat(Locale locale, int style)
    329      */
    330     @SuppressWarnings("unused")
    331     @Test
    332     public void TestTimeUnitFormat() {
    333         // Tests when "if (style < FULL_NAME || style >= TOTAL_STYLES)" is true
    334         // TOTAL_STYLES is 2
    335         int[] cases = { TimeUnitFormat.FULL_NAME - 1, TimeUnitFormat.FULL_NAME - 2, 3 };
    336         for (int i = 0; i < cases.length; i++) {
    337             try {
    338                 TimeUnitFormat tuf = new TimeUnitFormat(new ULocale("en_US"), cases[i]);
    339                 errln("TimeUnitFormat(ULocale,int) was suppose to return an " + "exception for a style value of "
    340                         + cases[i] + "passed into the constructor.");
    341             } catch (Exception e) {
    342             }
    343         }
    344         for (int i = 0; i < cases.length; i++) {
    345             try {
    346                 TimeUnitFormat tuf = new TimeUnitFormat(new Locale("en_US"), cases[i]);
    347                 errln("TimeUnitFormat(ULocale,int) was suppose to return an " + "exception for a style value of "
    348                         + cases[i] + "passed into the constructor.");
    349             } catch (Exception e) {
    350             }
    351         }
    352     }
    353 
    354     /*
    355      * Tests the method public TimeUnitFormat setLocale(ULocale locale) public TimeUnitFormat setLocale(Locale locale)
    356      */
    357     @Test
    358     public void TestSetLocale() {
    359         // Tests when "if ( locale != this.locale )" is false
    360         TimeUnitFormat tuf = new TimeUnitFormat(new ULocale("en_US"));
    361         if (!tuf.setLocale(new ULocale("en_US")).equals(tuf) && !tuf.setLocale(new Locale("en_US")).equals(tuf)) {
    362             errln("TimeUnitFormat.setLocale(ULocale) was suppose to "
    363                     + "return the same TimeUnitFormat object if the same " + "ULocale is entered as a parameter.");
    364         }
    365     }
    366 
    367     /*
    368      * Tests the method public TimeUnitFormat setNumberFormat(NumberFormat format)
    369      */
    370     @Test
    371     public void TestSetNumberFormat() {
    372         TimeUnitFormat tuf = new TimeUnitFormat();
    373 
    374         // Tests when "if (format == this.format)" is false
    375         // Tests when "if ( format == null )" is false
    376         tuf.setNumberFormat(NumberFormat.getInstance());
    377 
    378         // Tests when "if (format == this.format)" is true
    379         if (!tuf.setNumberFormat(NumberFormat.getInstance()).equals(tuf)) {
    380             errln("TimeUnitFormat.setNumberFormat(NumberFormat) was suppose to "
    381                     + "return the same object when the same NumberFormat is passed.");
    382         }
    383 
    384         // Tests when "if ( format == null )" is true
    385         // Tests when "if ( locale == null )" is true
    386         if (!tuf.setNumberFormat(null).equals(tuf)) {
    387             errln("TimeUnitFormat.setNumberFormat(NumberFormat) was suppose to "
    388                     + "return the same object when null is passed.");
    389         }
    390 
    391         TimeUnitFormat tuf1 = new TimeUnitFormat(new ULocale("en_US"));
    392 
    393         // Tests when "if ( locale == null )" is false
    394         tuf1.setNumberFormat(NumberFormat.getInstance());
    395         tuf1.setNumberFormat(null);
    396     }
    397 
    398     /*
    399      * Tests the method public StringBuffer format(Object obj, ...
    400      */
    401     @Test
    402     public void TestFormat() {
    403         TimeUnitFormat tuf = new TimeUnitFormat();
    404         try {
    405             tuf.format(new Integer("1"), null, null);
    406             errln("TimeUnitFormat.format(Object,StringBuffer,FieldPosition) "
    407                     + "was suppose to return an exception because the Object "
    408                     + "parameter was not of type TimeUnitAmount.");
    409         } catch (Exception e) {
    410         }
    411     }
    412 
    413     /* Tests the method private void setup() from
    414      * public Object parseObject(String source, ParsePosition pos)
    415      *
    416      */
    417     @Test
    418     public void TestSetup(){
    419         TimeUnitFormat tuf = new TimeUnitFormat();
    420         tuf.parseObject("", new ParsePosition(0));
    421 
    422         TimeUnitFormat tuf1 = new TimeUnitFormat();
    423         tuf1.setNumberFormat(NumberFormat.getInstance());
    424         tuf1.parseObject("", new ParsePosition(0));
    425     }
    426 
    427     @Test
    428     public void TestStandInForMeasureFormat() {
    429         TimeUnitFormat tuf = new TimeUnitFormat(ULocale.FRENCH, TimeUnitFormat.ABBREVIATED_NAME);
    430         Measure measure = new Measure(23, MeasureUnit.CELSIUS);
    431         assertEquals("23 C", "23 C", tuf.format(measure));
    432         tuf = new TimeUnitFormat(ULocale.FRENCH, TimeUnitFormat.FULL_NAME);
    433         assertEquals(
    434                 "70 pied et 5,3 pouces",
    435                 "70 pieds et 5,3 pouces",
    436                 tuf.formatMeasures(
    437                         new Measure(70, MeasureUnit.FOOT),
    438                         new Measure(5.3, MeasureUnit.INCH)));
    439         assertEquals("getLocale", ULocale.FRENCH, tuf.getLocale());
    440         assertEquals("getNumberFormat", ULocale.FRENCH, tuf.getNumberFormat().getLocale(ULocale.VALID_LOCALE));
    441         assertEquals("getWidth", MeasureFormat.FormatWidth.WIDE, tuf.getWidth());
    442     }
    443 
    444     private void verifyEqualsHashCode(Object o, Object eq, Object ne) {
    445         assertEquals("verifyEqualsHashCodeSame", o, o);
    446         assertEquals("verifyEqualsHashCodeEq", o, eq);
    447         assertNotEquals("verifyEqualsHashCodeNe", o, ne);
    448         assertNotEquals("verifyEqualsHashCodeEqTrans", eq, ne);
    449         assertEquals("verifyEqualsHashCodeHashEq", o.hashCode(), eq.hashCode());
    450 
    451         // May be a flaky test, but generally should be true.
    452         // May need to comment this out later.
    453         assertNotEquals("verifyEqualsHashCodeHashNe", o.hashCode(), ne.hashCode());
    454     }
    455 }
    456