1 /* 2 * Copyright (c) 2013, 2019, 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 * @bug 8206120 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.ResolverStyle; 48 import java.time.format.TextStyle; 49 import java.time.temporal.TemporalAccessor; 50 import java.time.temporal.TemporalQueries; 51 import java.util.Locale; 52 53 import org.testng.annotations.BeforeMethod; 54 import org.testng.annotations.DataProvider; 55 import org.testng.annotations.Test; 56 57 /** 58 * Test DateTimeFormatter with non-ISO chronology. 59 * 60 * Strings in test data are all dependent on CLDR data which may change 61 * in future CLDR releases. 62 */ 63 @Test 64 public class TestNonIsoFormatter { 65 private static final Chronology ISO8601 = IsoChronology.INSTANCE; 66 private static final Chronology JAPANESE = JapaneseChronology.INSTANCE; 67 private static final Chronology HIJRAH = HijrahChronology.INSTANCE; 68 private static final Chronology MINGUO = MinguoChronology.INSTANCE; 69 private static final Chronology BUDDHIST = ThaiBuddhistChronology.INSTANCE; 70 71 private static final LocalDate IsoDate = LocalDate.of(2013, 2, 11); 72 73 private static final Locale ARABIC = new Locale("ar"); 74 private static final Locale thTH = new Locale("th", "TH"); 75 private static final Locale thTHTH = Locale.forLanguageTag("th-TH-u-nu-thai"); 76 private static final Locale jaJPJP = Locale.forLanguageTag("ja-JP-u-ca-japanese"); 77 78 @BeforeMethod setUp()79 public void setUp() { 80 } 81 82 @DataProvider(name="format_data") formatData()83 Object[][] formatData() { 84 return new Object[][] { 85 // Chronology, Format Locale, Numbering Locale, ChronoLocalDate, expected string 86 { JAPANESE, Locale.JAPANESE, Locale.JAPANESE, JAPANESE.date(IsoDate), 87 "\u5e73\u621025\u5e742\u670811\u65e5\u6708\u66dc\u65e5" }, // Japanese Heisei 25-02-11 88 // Android-changed: requesting arabic numbering actually produces arabic digits. Also 89 // new CLDR patterns include the era. Test Arabic locale with ASCII digits below. 90 { HIJRAH, ARABIC, ARABIC, HIJRAH.date(IsoDate), 91 "\u0627\u0644\u0627\u062b\u0646\u064a\u0646\u060c \u0661 \u0631\u0628\u064a\u0639 " 92 + "\u0627\u0644\u0622\u062e\u0631 \u0661\u0664\u0663\u0664 \u0647\u0640" }, // Hijrah AH 1434-04-01 (Mon) 93 { HIJRAH, ARABIC, Locale.ENGLISH, HIJRAH.date(IsoDate), 94 "\u0627\u0644\u0627\u062b\u0646\u064a\u0646\u060c 1 \u0631\u0628\u064a\u0639 " 95 + "\u0627\u0644\u0622\u062e\u0631 1434 \u0647\u0640" }, // Hijrah AH 1434-04-01 (Mon) 96 { MINGUO, Locale.TAIWAN, Locale.TAIWAN, MINGUO.date(IsoDate), 97 "\u6c11\u570b102\u5e742\u670811\u65e5 \u661f\u671f\u4e00" }, // Minguo ROC 102-02-11 (Mon) 98 { BUDDHIST, thTH, thTH, BUDDHIST.date(IsoDate), 99 "\u0e27\u0e31\u0e19\u0e08\u0e31\u0e19\u0e17\u0e23\u0e4c\u0e17\u0e35\u0e48 " 100 + "11 \u0e01\u0e38\u0e21\u0e20\u0e32\u0e1e\u0e31\u0e19\u0e18\u0e4c " 101 + "\u0e1e.\u0e28. 2556" }, // ThaiBuddhist BE 2556-02-11 102 { BUDDHIST, thTH, thTHTH, BUDDHIST.date(IsoDate), 103 "\u0e27\u0e31\u0e19\u0e08\u0e31\u0e19\u0e17\u0e23\u0e4c\u0e17\u0e35\u0e48 \u0e51\u0e51 " 104 + "\u0e01\u0e38\u0e21\u0e20\u0e32\u0e1e\u0e31\u0e19\u0e18\u0e4c " 105 + "\u0e1e.\u0e28. \u0e52\u0e55\u0e55\u0e56" }, // ThaiBuddhist BE 2556-02-11 (with Thai digits) 106 }; 107 } 108 109 @DataProvider(name="invalid_text") invalidText()110 Object[][] invalidText() { 111 return new Object[][] { 112 // TODO: currently fixed Chronology and Locale. 113 // line commented out, as S64.01.09 seems like a reasonable thing to parse 114 // (era "S" ended on S64.01.07, but a little leniency is a good thing 115 // { "\u662d\u548c64\u5e741\u67089\u65e5\u6708\u66dc\u65e5" }, // S64.01.09 (Mon) 116 { "\u662d\u548c65\u5e741\u67081\u65e5\u6708\u66dc\u65e5" }, // S65.01.01 (Mon) 117 }; 118 } 119 120 @DataProvider(name="chrono_names") chronoNamesData()121 Object[][] chronoNamesData() { 122 return new Object[][] { 123 // Chronology, Locale, Chronology Name 124 // Android-changed: CLDR data has changed. 125 { ISO8601, Locale.ENGLISH, "ISO-8601 Calendar" }, 126 { BUDDHIST, Locale.ENGLISH, "Buddhist Calendar" }, 127 { HIJRAH, Locale.ENGLISH, "Islamic Calendar (Umm al-Qura)" }, 128 { JAPANESE, Locale.ENGLISH, "Japanese Calendar" }, 129 { MINGUO, Locale.ENGLISH, "Minguo Calendar" }, 130 131 { ISO8601, Locale.JAPANESE, "ISO-8601" }, 132 { JAPANESE, Locale.JAPANESE, "\u548c\u66a6" }, 133 { BUDDHIST, Locale.JAPANESE, "\u4ecf\u66a6" }, 134 135 { ISO8601, thTH, "\u0e1b\u0e0f\u0e34\u0e17\u0e34\u0e19 ISO-8601" }, 136 { JAPANESE, thTH, "\u0e1b\u0e0f\u0e34\u0e17\u0e34\u0e19\u0e0d\u0e35\u0e48\u0e1b\u0e38\u0e48\u0e19" }, 137 { BUDDHIST, thTH, "\u0e1b\u0e0f\u0e34\u0e17\u0e34\u0e19\u0e1e\u0e38\u0e17\u0e18" }, 138 139 { HIJRAH, ARABIC, "\u0627\u0644\u062a\u0642\u0648\u064a\u0645 " 140 + "\u0627\u0644\u0625\u0633\u0644\u0627\u0645\u064a " 141 + "(\u0623\u0645 \u0627\u0644\u0642\u0631\u0649)" }, // JDK-8015986 142 }; 143 } 144 145 @DataProvider(name="lenient_eraYear") lenientEraYear()146 Object[][] lenientEraYear() { 147 return new Object[][] { 148 // Chronology, lenient era/year, strict era/year 149 { JAPANESE, "Meiji 123", "Heisei 2" }, 150 // Android-changed: Eras names have been changed in CLDR data. 151 // { JAPANESE, "Showa 65", "Heisei 2" } 152 { JAPANESE, "Shōwa 65", "Heisei 2" }, 153 { JAPANESE, "Heisei 32", "Reiwa 2" }, 154 }; 155 } 156 157 @Test(dataProvider="format_data") test_formatLocalizedDate(Chronology chrono, Locale formatLocale, Locale numberingLocale, ChronoLocalDate date, String expected)158 public void test_formatLocalizedDate(Chronology chrono, Locale formatLocale, Locale numberingLocale, 159 ChronoLocalDate date, String expected) { 160 DateTimeFormatter dtf = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL) 161 .withChronology(chrono).withLocale(formatLocale) 162 .withDecimalStyle(DecimalStyle.of(numberingLocale)); 163 String text = dtf.format(date); 164 assertEquals(text, expected); 165 } 166 167 @Test(dataProvider="format_data") test_parseLocalizedText(Chronology chrono, Locale formatLocale, Locale numberingLocale, ChronoLocalDate expected, String text)168 public void test_parseLocalizedText(Chronology chrono, Locale formatLocale, Locale numberingLocale, 169 ChronoLocalDate expected, String text) { 170 DateTimeFormatter dtf = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL) 171 .withChronology(chrono).withLocale(formatLocale) 172 .withDecimalStyle(DecimalStyle.of(numberingLocale)); 173 TemporalAccessor temporal = dtf.parse(text); 174 ChronoLocalDate date = chrono.date(temporal); 175 assertEquals(date, expected); 176 } 177 178 @Test(dataProvider="invalid_text", expectedExceptions=DateTimeParseException.class) test_parseInvalidText(String text)179 public void test_parseInvalidText(String text) { 180 DateTimeFormatter dtf = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL) 181 .withChronology(JAPANESE).withLocale(Locale.JAPANESE); 182 dtf.parse(text); 183 } 184 185 @Test(dataProvider="chrono_names") test_chronoNames(Chronology chrono, Locale locale, String expected)186 public void test_chronoNames(Chronology chrono, Locale locale, String expected) { 187 DateTimeFormatter dtf = new DateTimeFormatterBuilder().appendChronologyText(TextStyle.SHORT) 188 .toFormatter(locale); 189 String text = dtf.format(chrono.dateNow()); 190 assertEquals(text, expected); 191 TemporalAccessor ta = dtf.parse(text); 192 Chronology cal = ta.query(TemporalQueries.chronology()); 193 assertEquals(cal, chrono); 194 } 195 196 @Test(dataProvider="lenient_eraYear") test_lenientEraYear(Chronology chrono, String lenient, String strict)197 public void test_lenientEraYear(Chronology chrono, String lenient, String strict) { 198 String mdStr = "-01-01"; 199 DateTimeFormatter dtf = new DateTimeFormatterBuilder() 200 .appendPattern("GGGG y-M-d") 201 .toFormatter() 202 .withChronology(chrono); 203 DateTimeFormatter dtfLenient = dtf.withResolverStyle(ResolverStyle.LENIENT); 204 assertEquals(LocalDate.parse(lenient+mdStr, dtfLenient), LocalDate.parse(strict+mdStr, dtf)); 205 } 206 } 207