1 /* 2 * Copyright (c) 2012, 2013, 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 package test.java.time.format; 25 26 import static org.testng.Assert.assertEquals; 27 28 import java.text.DateFormatSymbols; 29 import java.time.ZoneId; 30 import java.time.ZonedDateTime; 31 import java.time.format.DecimalStyle; 32 import java.time.format.DateTimeFormatter; 33 import java.time.format.DateTimeFormatterBuilder; 34 import java.time.format.TextStyle; 35 import java.time.temporal.ChronoField; 36 import java.time.temporal.TemporalQueries; 37 import java.time.zone.ZoneRulesProvider; 38 import java.util.Arrays; 39 import java.util.Date; 40 import java.util.HashSet; 41 import java.util.Locale; 42 import java.util.Random; 43 import java.util.Set; 44 import java.util.TimeZone; 45 46 import org.testng.annotations.DataProvider; 47 import org.testng.annotations.Test; 48 49 /** 50 * Test ZoneTextPrinterParser 51 */ 52 @Test 53 public class TestZoneTextPrinterParser extends AbstractTestPrinterParser { 54 55 protected static DateTimeFormatter getFormatter(Locale locale, TextStyle style) { 56 return new DateTimeFormatterBuilder().appendZoneText(style) 57 .toFormatter(locale) 58 .withDecimalStyle(DecimalStyle.of(locale)); 59 } 60 61 public void test_printText() { 62 Random r = new Random(); 63 int N = 50; 64 Locale[] locales = Locale.getAvailableLocales(); 65 Set<String> zids = ZoneRulesProvider.getAvailableZoneIds(); 66 ZonedDateTime zdt = ZonedDateTime.now(); 67 68 //System.out.printf("locale==%d, timezone=%d%n", locales.length, zids.size()); 69 while (N-- > 0) { 70 zdt = zdt.withDayOfYear(r.nextInt(365) + 1) 71 .with(ChronoField.SECOND_OF_DAY, r.nextInt(86400)); 72 for (String zid : zids) { 73 if (zid.equals("ROC") || zid.startsWith("Etc/GMT")) { 74 continue; // TBD: match jdk behavior? 75 } 76 zdt = zdt.withZoneSameLocal(ZoneId.of(zid)); 77 TimeZone tz = TimeZone.getTimeZone(zid); 78 boolean isDST = tz.inDaylightTime(new Date(zdt.toInstant().toEpochMilli())); 79 for (Locale locale : locales) { 80 printText(locale, zdt, TextStyle.FULL, tz, 81 tz.getDisplayName(isDST, TimeZone.LONG, locale)); 82 printText(locale, zdt, TextStyle.SHORT, tz, 83 tz.getDisplayName(isDST, TimeZone.SHORT, locale)); 84 } 85 } 86 } 87 } 88 89 private void printText(Locale locale, ZonedDateTime zdt, TextStyle style, TimeZone zone, String expected) { 90 String result = getFormatter(locale, style).format(zdt); 91 if (!result.equals(expected)) { 92 if (result.equals("FooLocation")) { // from rules provider test if same vm 93 return; 94 } 95 System.out.println("----------------"); 96 System.out.printf("tdz[%s]%n", zdt.toString()); 97 System.out.printf("[%-5s, %5s] :[%s]%n", locale.toString(), style.toString(),result); 98 System.out.printf(" %5s, %5s :[%s] %s%n", "", "", expected, zone); 99 } 100 assertEquals(result, expected); 101 } 102 103 public void test_ParseText() { 104 Locale[] locales = new Locale[] { Locale.ENGLISH, Locale.JAPANESE, Locale.FRENCH }; 105 Set<String> zids = ZoneRulesProvider.getAvailableZoneIds(); 106 for (Locale locale : locales) { 107 parseText(zids, locale, TextStyle.FULL, false); 108 parseText(zids, locale, TextStyle.FULL, true); 109 parseText(zids, locale, TextStyle.SHORT, false); 110 parseText(zids, locale, TextStyle.SHORT, true); 111 } 112 } 113 114 private static Set<ZoneId> preferred = new HashSet<>(Arrays.asList(new ZoneId[] { 115 ZoneId.of("EST", ZoneId.SHORT_IDS), 116 ZoneId.of("Asia/Taipei"), 117 ZoneId.of("CET"), 118 })); 119 120 private static Set<ZoneId> preferred_s = new HashSet<>(Arrays.asList(new ZoneId[] { 121 ZoneId.of("EST", ZoneId.SHORT_IDS), 122 ZoneId.of("CET"), 123 ZoneId.of("Australia/South"), 124 ZoneId.of("Australia/West"), 125 ZoneId.of("Asia/Shanghai"), 126 })); 127 128 private static Set<ZoneId> none = new HashSet<>(); 129 130 @DataProvider(name="preferredZones") 131 Object[][] data_preferredZones() { 132 return new Object[][] { 133 {"America/New_York", "Eastern Standard Time", none, Locale.ENGLISH, TextStyle.FULL}, 134 // {"EST", "Eastern Standard Time", preferred, Locale.ENGLISH, TextStyle.FULL}, 135 {"Europe/Paris", "Central European Time", none, Locale.ENGLISH, TextStyle.FULL}, 136 {"CET", "Central European Time", preferred, Locale.ENGLISH, TextStyle.FULL}, 137 {"Asia/Shanghai", "China Standard Time", none, Locale.ENGLISH, TextStyle.FULL}, 138 {"Asia/Taipei", "China Standard Time", preferred, Locale.ENGLISH, TextStyle.FULL}, 139 {"America/Chicago", "CST", none, Locale.ENGLISH, TextStyle.SHORT}, 140 {"Asia/Taipei", "CST", preferred, Locale.ENGLISH, TextStyle.SHORT}, 141 {"Australia/South", "CST", preferred_s, Locale.ENGLISH, TextStyle.SHORT}, 142 {"America/Chicago", "CDT", none, Locale.ENGLISH, TextStyle.SHORT}, 143 {"Asia/Shanghai", "CDT", preferred_s, Locale.ENGLISH, TextStyle.SHORT}, 144 }; 145 } 146 147 @Test(dataProvider="preferredZones") 148 public void test_ParseText(String expected, String text, Set<ZoneId> preferred, Locale locale, TextStyle style) { 149 DateTimeFormatter fmt = new DateTimeFormatterBuilder().appendZoneText(style, preferred) 150 .toFormatter(locale) 151 .withDecimalStyle(DecimalStyle.of(locale)); 152 153 String ret = fmt.parse(text, TemporalQueries.zone()).getId(); 154 155 System.out.printf("[%-5s %s] %24s -> %s(%s)%n", 156 locale.toString(), 157 style == TextStyle.FULL ? " full" :"short", 158 text, ret, expected); 159 160 assertEquals(ret, expected); 161 162 } 163 164 165 private void parseText(Set<String> zids, Locale locale, TextStyle style, boolean ci) { 166 System.out.println("---------------------------------------"); 167 DateTimeFormatter fmt = getFormatter(locale, style, ci); 168 for (String[] names : new DateFormatSymbols(locale).getZoneStrings()) { 169 if (!zids.contains(names[0])) { 170 continue; 171 } 172 String zid = names[0]; 173 String expected = ZoneName.toZid(zid, locale); 174 175 parse(fmt, zid, expected, zid, locale, style, ci); 176 int i = style == TextStyle.FULL ? 1 : 2; 177 for (; i < names.length; i += 2) { 178 parse(fmt, zid, expected, names[i], locale, style, ci); 179 } 180 } 181 } 182 183 private void parse(DateTimeFormatter fmt, 184 String zid, String expected, String text, 185 Locale locale, TextStyle style, boolean ci) { 186 if (ci) { 187 text = text.toUpperCase(); 188 } 189 String ret = fmt.parse(text, TemporalQueries.zone()).getId(); 190 // TBD: need an excluding list 191 // assertEquals(...); 192 if (ret.equals(expected) || 193 ret.equals(zid) || 194 ret.equals(ZoneName.toZid(zid)) || 195 ret.equals(expected.replace("UTC", "UCT"))) { 196 return; 197 } 198 System.out.printf("[%-5s %s %s %16s] %24s -> %s(%s)%n", 199 locale.toString(), 200 ci ? "ci" : " ", 201 style == TextStyle.FULL ? " full" :"short", 202 zid, text, ret, expected); 203 } 204 205 private DateTimeFormatter getFormatter(Locale locale, TextStyle style, boolean ci) { 206 DateTimeFormatterBuilder db = new DateTimeFormatterBuilder(); 207 if (ci) { 208 db = db.parseCaseInsensitive(); 209 } 210 return db.appendZoneText(style) 211 .toFormatter(locale) 212 .withDecimalStyle(DecimalStyle.of(locale)); 213 } 214 215 }