1 /* 2 * Copyright (c) 2017, 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 8176841 28 * @summary Tests java.time classes deals with Unicode extensions 29 * correctly. 30 * @modules jdk.localedata 31 * @run testng/othervm -Djava.locale.providers=CLDR JavaTimeTests 32 */ 33 34 import static org.testng.Assert.assertEquals; 35 36 import java.time.DayOfWeek; 37 import java.time.ZonedDateTime; 38 import java.time.ZoneId; 39 import java.time.chrono.Chronology; 40 import java.time.chrono.HijrahChronology; 41 import java.time.chrono.JapaneseChronology; 42 import java.time.format.DateTimeFormatter; 43 import java.time.format.DateTimeFormatterBuilder; 44 import java.time.format.FormatStyle; 45 import java.time.temporal.WeekFields; 46 import java.util.Locale; 47 import java.util.TimeZone; 48 49 import org.testng.annotations.AfterTest; 50 import org.testng.annotations.BeforeTest; 51 import org.testng.annotations.DataProvider; 52 import org.testng.annotations.Test; 53 54 /** 55 * Test JavaTime with BCP47 U extensions 56 */ 57 @Test 58 public class JavaTimeTests { 59 private static TimeZone defaultTZ; 60 61 private static final Chronology JAPANESE = JapaneseChronology.INSTANCE; 62 private static final Chronology HIJRAH = HijrahChronology.INSTANCE; 63 64 private static final ZoneId ASIATOKYO = ZoneId.of("Asia/Tokyo"); 65 private static final ZoneId AMLA = ZoneId.of("America/Los_Angeles"); 66 67 private static final Locale JPTYO = Locale.forLanguageTag("en-u-tz-jptyo"); 68 private static final Locale JCAL = Locale.forLanguageTag("en-u-ca-japanese"); 69 private static final Locale HCAL = Locale.forLanguageTag("en-u-ca-islamic-umalqura"); 70 71 private static final Locale FW_SUN = Locale.forLanguageTag("en-US-u-fw-sun"); 72 private static final Locale FW_MON = Locale.forLanguageTag("en-US-u-fw-mon"); 73 private static final Locale FW_TUE = Locale.forLanguageTag("en-US-u-fw-tue"); 74 private static final Locale FW_WED = Locale.forLanguageTag("en-US-u-fw-wed"); 75 private static final Locale FW_THU = Locale.forLanguageTag("en-US-u-fw-thu"); 76 private static final Locale FW_FRI = Locale.forLanguageTag("en-US-u-fw-fri"); 77 private static final Locale FW_SAT = Locale.forLanguageTag("en-US-u-fw-sat"); 78 79 private static final Locale RG_GB = Locale.forLanguageTag("en-US-u-rg-gbzzzz"); 80 81 private static final ZonedDateTime ZDT = ZonedDateTime.of(2017, 8, 10, 15, 15, 0, 0, AMLA); 82 83 private static final String PATTERN = "GGGG MMMM-dd-uu HH:mm:ss zzzz"; 84 85 @BeforeTest 86 public void beforeTest() { 87 defaultTZ = TimeZone.getDefault(); 88 TimeZone.setDefault(TimeZone.getTimeZone(AMLA)); 89 } 90 91 @AfterTest 92 public void afterTest() { 93 TimeZone.setDefault(defaultTZ); 94 } 95 96 @DataProvider(name="withLocale") 97 Object[][] withLocale() { 98 return new Object[][] { 99 // Locale, Chrono override, Zone override, Expected Chrono, Expected Zone, 100 // Expected formatted string 101 {Locale.JAPAN, null, null, null, null, 102 "2017\u5e748\u670810\u65e5\u6728\u66dc\u65e5 15\u664215\u520600\u79d2 \u30a2\u30e1\u30ea\u30ab\u592a\u5e73\u6d0b\u590f\u6642\u9593" 103 }, 104 {Locale.JAPAN, JAPANESE, null, JAPANESE, null, 105 "\u5e73\u621029\u5e748\u670810\u65e5\u6728\u66dc\u65e5 15\u664215\u520600\u79d2 \u30a2\u30e1\u30ea\u30ab\u592a\u5e73\u6d0b\u590f\u6642\u9593" 106 }, 107 {Locale.JAPAN, JAPANESE, ASIATOKYO, JAPANESE, ASIATOKYO, 108 "\u5e73\u621029\u5e748\u670811\u65e5\u91d1\u66dc\u65e5 7\u664215\u520600\u79d2 \u65e5\u672c\u6a19\u6e96\u6642" 109 }, 110 111 {JCAL, null, null, JAPANESE, null, 112 "Thursday, August 10, 29 Heisei at 3:15:00 PM Pacific Daylight Time" 113 }, 114 {JCAL, HIJRAH, null, JAPANESE, null, 115 "Thursday, August 10, 29 Heisei at 3:15:00 PM Pacific Daylight Time" 116 }, 117 {HCAL, JAPANESE, null, HIJRAH, null, 118 "Thursday, Dhu\u02bbl-Qi\u02bbdah 18, 1438 AH at 3:15:00 PM Pacific Daylight Time" 119 }, 120 121 122 {JPTYO, null, null, null, ASIATOKYO, 123 "Friday, August 11, 2017 at 7:15:00 AM Japan Standard Time" 124 }, 125 {JPTYO, null, AMLA, null, ASIATOKYO, 126 "Friday, August 11, 2017 at 7:15:00 AM Japan Standard Time" 127 }, 128 // invalid tz 129 {Locale.forLanguageTag("en-US-u-tz-jpzzz"), null, null, null, null, 130 "Thursday, August 10, 2017 at 3:15:00 PM Pacific Daylight Time" 131 }, 132 {Locale.forLanguageTag("en-US-u-tz-jpzzz"), null, AMLA, null, AMLA, 133 "Thursday, August 10, 2017 at 3:15:00 PM Pacific Daylight Time" 134 }, 135 136 {RG_GB, null, null, null, null, 137 "Thursday, 10 August 2017 at 15:15:00 Pacific Daylight Time" 138 }, 139 }; 140 } 141 142 @DataProvider(name="firstDayOfWeek") 143 Object[][] firstDayOfWeek () { 144 return new Object[][] { 145 // Locale, Expected DayOfWeek, 146 {Locale.US, DayOfWeek.SUNDAY}, 147 {FW_SUN, DayOfWeek.SUNDAY}, 148 {FW_MON, DayOfWeek.MONDAY}, 149 {FW_TUE, DayOfWeek.TUESDAY}, 150 {FW_WED, DayOfWeek.WEDNESDAY}, 151 {FW_THU, DayOfWeek.THURSDAY}, 152 {FW_FRI, DayOfWeek.FRIDAY}, 153 {FW_SAT, DayOfWeek.SATURDAY}, 154 155 // invalid case 156 {Locale.forLanguageTag("en-US-u-fw-xxx"), DayOfWeek.SUNDAY}, 157 158 // region override 159 {RG_GB, DayOfWeek.MONDAY}, 160 {Locale.forLanguageTag("zh-CN-u-rg-eszzzz"), DayOfWeek.MONDAY}, 161 162 // "fw" and "rg". 163 {Locale.forLanguageTag("en-US-u-fw-wed-rg-gbzzzz"), DayOfWeek.WEDNESDAY}, 164 {Locale.forLanguageTag("en-US-u-fw-xxx-rg-gbzzzz"), DayOfWeek.MONDAY}, 165 {Locale.forLanguageTag("en-US-u-fw-xxx-rg-zzzz"), DayOfWeek.SUNDAY}, 166 }; 167 } 168 169 @DataProvider(name="minDaysInFirstWeek") 170 Object[][] minDaysInFrstWeek () { 171 return new Object[][] { 172 // Locale, Expected minDay, 173 {Locale.US, 1}, 174 175 // region override 176 {RG_GB, 4}, 177 {Locale.forLanguageTag("zh-CN-u-rg-eszzzz"), 4}, 178 }; 179 } 180 181 @DataProvider(name="ofPattern") 182 Object[][] ofPattern() { 183 return new Object[][] { 184 // Locale, Expected Chrono, Expected Zone, 185 // Expected formatted string 186 {JCAL, JAPANESE, null, 187 "Heisei August-10-17 15:15:00 Pacific Daylight Time" 188 }, 189 {HCAL, HIJRAH, null, 190 "AH Dhu\u02bbl-Qi\u02bbdah-18-38 15:15:00 Pacific Daylight Time" 191 }, 192 193 {JPTYO, null, ASIATOKYO, 194 "Anno Domini August-11-17 07:15:00 Japan Standard Time" 195 }, 196 {Locale.forLanguageTag("en-US-u-tz-jpzzz"), null, null, 197 "Anno Domini August-10-17 15:15:00 Pacific Daylight Time" 198 }, 199 200 {RG_GB, null, null, 201 "Anno Domini August-10-17 15:15:00 Pacific Daylight Time" 202 }, 203 204 }; 205 } 206 207 @Test(dataProvider="withLocale") 208 public void test_withLocale(Locale locale, Chronology chrono, ZoneId zone, 209 Chronology chronoExpected, ZoneId zoneExpected, 210 String formatExpected) { 211 DateTimeFormatter dtf = 212 DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL, FormatStyle.FULL) 213 .withChronology(chrono).withZone(zone).withLocale(locale); 214 assertEquals(dtf.getChronology(), chronoExpected); 215 assertEquals(dtf.getZone(), zoneExpected); 216 String formatted = dtf.format(ZDT); 217 assertEquals(formatted, formatExpected); 218 assertEquals(dtf.parse(formatted, ZonedDateTime::from), 219 zoneExpected != null ? ZDT.withZoneSameInstant(zoneExpected) : ZDT); 220 } 221 222 @Test(dataProvider="firstDayOfWeek") 223 public void test_firstDayOfWeek(Locale locale, DayOfWeek dowExpected) { 224 DayOfWeek dow = WeekFields.of(locale).getFirstDayOfWeek(); 225 assertEquals(dow, dowExpected); 226 } 227 228 @Test(dataProvider="minDaysInFirstWeek") 229 public void test_minDaysInFirstWeek(Locale locale, int minDaysExpected) { 230 int minDays = WeekFields.of(locale).getMinimalDaysInFirstWeek(); 231 assertEquals(minDays, minDaysExpected); 232 } 233 234 @Test(dataProvider="ofPattern") 235 public void test_ofPattern(Locale locale, 236 Chronology chronoExpected, ZoneId zoneExpected, 237 String formatExpected) { 238 DateTimeFormatter dtf = 239 DateTimeFormatter.ofPattern(PATTERN, locale); 240 assertEquals(dtf.getChronology(), chronoExpected); 241 assertEquals(dtf.getZone(), zoneExpected); 242 String formatted = dtf.format(ZDT); 243 assertEquals(formatted, formatExpected); 244 assertEquals(dtf.parse(formatted, ZonedDateTime::from), 245 zoneExpected != null ? ZDT.withZoneSameInstant(zoneExpected) : ZDT); 246 } 247 248 @Test(dataProvider="ofPattern") 249 public void test_toFormatter(Locale locale, 250 Chronology chronoExpected, ZoneId zoneExpected, 251 String formatExpected) { 252 DateTimeFormatter dtf = 253 new DateTimeFormatterBuilder().appendPattern(PATTERN).toFormatter(locale); 254 assertEquals(dtf.getChronology(), chronoExpected); 255 assertEquals(dtf.getZone(), zoneExpected); 256 String formatted = dtf.format(ZDT); 257 assertEquals(formatted, formatExpected); 258 assertEquals(dtf.parse(formatted, ZonedDateTime::from), 259 zoneExpected != null ? ZDT.withZoneSameInstant(zoneExpected) : ZDT); 260 } 261 }