1 /*
   2  * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  *
  26  * @test
  27  * @modules jdk.localedata
  28  */
  29 
  30 package test.java.time.format;
  31 
  32 import static org.testng.Assert.assertEquals;
  33 
  34 import java.time.LocalDate;
  35 import java.time.chrono.ChronoLocalDate;
  36 import java.time.chrono.Chronology;
  37 import java.time.chrono.HijrahChronology;
  38 import java.time.chrono.IsoChronology;
  39 import java.time.chrono.JapaneseChronology;
  40 import java.time.chrono.MinguoChronology;
  41 import java.time.chrono.ThaiBuddhistChronology;
  42 import java.time.format.DecimalStyle;
  43 import java.time.format.DateTimeFormatter;
  44 import java.time.format.DateTimeFormatterBuilder;
  45 import java.time.format.DateTimeParseException;
  46 import java.time.format.FormatStyle;
  47 import java.time.format.TextStyle;
  48 import java.time.temporal.TemporalAccessor;
  49 import java.time.temporal.TemporalQueries;
  50 import java.util.Locale;
  51 
  52 import org.testng.annotations.BeforeMethod;
  53 import org.testng.annotations.DataProvider;
  54 import org.testng.annotations.Test;
  55 
  56 /**
  57  * Test DateTimeFormatter with non-ISO chronology.
  58  *
  59  * Strings in test data are all dependent on CLDR data which may change
  60  * in future CLDR releases.
  61  */
  62 @Test
  63 public class TestNonIsoFormatter {
  64     private static final Chronology ISO8601 = IsoChronology.INSTANCE;
  65     private static final Chronology JAPANESE = JapaneseChronology.INSTANCE;
  66     private static final Chronology HIJRAH = HijrahChronology.INSTANCE;
  67     private static final Chronology MINGUO = MinguoChronology.INSTANCE;
  68     private static final Chronology BUDDHIST = ThaiBuddhistChronology.INSTANCE;
  69 
  70     private static final LocalDate IsoDate = LocalDate.of(2013, 2, 11);
  71 
  72     private static final Locale ARABIC = new Locale("ar");
  73     private static final Locale thTH = new Locale("th", "TH");
  74     private static final Locale thTHTH = Locale.forLanguageTag("th-TH-u-nu-thai");
  75     private static final Locale jaJPJP = Locale.forLanguageTag("ja-JP-u-ca-japanese");
  76 
  77     @BeforeMethod
  78     public void setUp() {
  79     }
  80 
  81     @DataProvider(name="format_data")
  82     Object[][] formatData() {
  83         return new Object[][] {
  84             // Chronology, Format Locale, Numbering Locale, ChronoLocalDate, expected string
  85             { JAPANESE, Locale.JAPANESE, Locale.JAPANESE, JAPANESE.date(IsoDate),
  86               "\u5e73\u621025\u5e742\u670811\u65e5\u6708\u66dc\u65e5" }, // Japanese Heisei 25-02-11
  87             { HIJRAH, ARABIC, ARABIC, HIJRAH.date(IsoDate),
  88               "\u0627\u0644\u0627\u062b\u0646\u064a\u0646\u060c \u0661 \u0631\u0628\u064a\u0639 "
  89               + "\u0627\u0644\u0622\u062e\u0631\u060c \u0661\u0664\u0663\u0664 \u0647\u0640" }, // Hijrah AH 1434-04-01 (Mon)
  90             { MINGUO, Locale.TAIWAN, Locale.TAIWAN, MINGUO.date(IsoDate),
  91               "\u6c11\u570b102\u5e742\u670811\u65e5 \u661f\u671f\u4e00" }, // Minguo ROC 102-02-11 (Mon)
  92             { BUDDHIST, thTH, thTH, BUDDHIST.date(IsoDate),
  93               "\u0e27\u0e31\u0e19\u0e08\u0e31\u0e19\u0e17\u0e23\u0e4c\u0e17\u0e35\u0e48"
  94               + " 11 \u0e01\u0e38\u0e21\u0e20\u0e32\u0e1e\u0e31\u0e19\u0e18\u0e4c"
  95               + " \u0e1e.\u0e28. 2556" }, // ThaiBuddhist BE 2556-02-11
  96             { BUDDHIST, thTH, thTHTH, BUDDHIST.date(IsoDate),
  97               "\u0e27\u0e31\u0e19\u0e08\u0e31\u0e19\u0e17\u0e23\u0e4c\u0e17\u0e35\u0e48 \u0e51\u0e51 "
  98               + "\u0e01\u0e38\u0e21\u0e20\u0e32\u0e1e\u0e31\u0e19\u0e18\u0e4c \u0e1e.\u0e28. "
  99               + "\u0e52\u0e55\u0e55\u0e56" }, // ThaiBuddhist BE 2556-02-11 (with Thai digits)
 100         };
 101     }
 102 
 103     @DataProvider(name="invalid_text")
 104     Object[][] invalidText() {
 105         return new Object[][] {
 106             // TODO: currently fixed Chronology and Locale.
 107             // line commented out, as S64.01.09 seems like a reasonable thing to parse
 108             // (era "S" ended on S64.01.07, but a little leniency is a good thing
 109 //            { "\u662d\u548c64\u5e741\u67089\u65e5\u6708\u66dc\u65e5" }, // S64.01.09 (Mon)
 110             { "\u662d\u548c65\u5e741\u67081\u65e5\u6708\u66dc\u65e5" }, // S65.01.01 (Mon)
 111         };
 112     }
 113 
 114     @DataProvider(name="chrono_names")
 115     Object[][] chronoNamesData() {
 116         return new Object[][] {
 117             // Chronology, Locale, Chronology Name
 118             { ISO8601,  Locale.ENGLISH, "ISO" },    // No data in CLDR; Use Id.
 119             { BUDDHIST, Locale.ENGLISH, "Buddhist Calendar" },
 120             { HIJRAH,   Locale.ENGLISH, "Islamic Calendar (Umm al-Qura)" },
 121             { JAPANESE, Locale.ENGLISH, "Japanese Calendar" },
 122             { MINGUO,   Locale.ENGLISH, "Minguo Calendar" },
 123 
 124             { ISO8601,  Locale.JAPANESE, "ISO" },    // No data in CLDR; Use Id.
 125             { JAPANESE, Locale.JAPANESE, "\u548c\u66a6" },
 126             { BUDDHIST, Locale.JAPANESE, "\u30bf\u30a4\u4ecf\u6559\u66a6" },
 127 
 128             { ISO8601,  thTH, "ISO" },    // No data in CLDR; Use Id.
 129             { JAPANESE, thTH, "\u0e1b\u0e0f\u0e34\u0e17\u0e34\u0e19\u0e0d\u0e35\u0e48\u0e1b\u0e38\u0e48\u0e19" },
 130             { BUDDHIST, thTH, "\u0e1b\u0e0f\u0e34\u0e17\u0e34\u0e19\u0e1e\u0e38\u0e17\u0e18" },
 131 
 132             { HIJRAH,   ARABIC, "\u0627\u0644\u062a\u0642\u0648\u064a\u0645 "
 133                                 + "\u0627\u0644\u0625\u0633\u0644\u0627\u0645\u064a "
 134                                 + "(\u0623\u0645 \u0627\u0644\u0642\u0631\u0649)" },
 135         };
 136     }
 137 
 138     @Test(dataProvider="format_data")
 139     public void test_formatLocalizedDate(Chronology chrono, Locale formatLocale, Locale numberingLocale,
 140                                          ChronoLocalDate date, String expected) {
 141         DateTimeFormatter dtf = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)
 142             .withChronology(chrono).withLocale(formatLocale)
 143             .withDecimalStyle(DecimalStyle.of(numberingLocale));
 144         String text = dtf.format(date);
 145         assertEquals(text, expected);
 146     }
 147 
 148     @Test(dataProvider="format_data")
 149     public void test_parseLocalizedText(Chronology chrono, Locale formatLocale, Locale numberingLocale,
 150                                         ChronoLocalDate expected, String text) {
 151         DateTimeFormatter dtf = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)
 152             .withChronology(chrono).withLocale(formatLocale)
 153             .withDecimalStyle(DecimalStyle.of(numberingLocale));
 154         TemporalAccessor temporal = dtf.parse(text);
 155         ChronoLocalDate date = chrono.date(temporal);
 156         assertEquals(date, expected);
 157     }
 158 
 159     @Test(dataProvider="invalid_text", expectedExceptions=DateTimeParseException.class)
 160     public void test_parseInvalidText(String text) {
 161         DateTimeFormatter dtf = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)
 162             .withChronology(JAPANESE).withLocale(Locale.JAPANESE);
 163         dtf.parse(text);
 164     }
 165 
 166     @Test(dataProvider="chrono_names")
 167     public void test_chronoNames(Chronology chrono, Locale locale, String expected) {
 168         DateTimeFormatter dtf = new DateTimeFormatterBuilder().appendChronologyText(TextStyle.SHORT)
 169             .toFormatter(locale);
 170         String text = dtf.format(chrono.dateNow());
 171         assertEquals(text, expected);
 172         TemporalAccessor ta = dtf.parse(text);
 173         Chronology cal = ta.query(TemporalQueries.chronology());
 174         assertEquals(cal, chrono);
 175     }
 176 }