1 /* 2 * Copyright (c) 2012, 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 * @test 26 * @bug 8007572 8008161 8157792 8212970 8224560 27 * @summary Test whether the TimeZone generated from JSR310 tzdb is the same 28 * as the one from the tz data from javazic 29 * @modules java.base/sun.util.calendar:+open 30 * @build BackEnd Checksum DayOfWeek Gen GenDoc Main Mappings Month 31 * Rule RuleDay RuleRec Simple TestZoneInfo310 Time Timezone 32 * TzIDOldMapping Zone ZoneInfoFile ZoneInfoOld ZoneRec Zoneinfo 33 * @run main TestZoneInfo310 34 */ 35 36 import java.io.File; 37 import java.lang.reflect.*; 38 import java.nio.file.*; 39 import java.util.*; 40 import java.util.regex.*; 41 import java.time.zone.*; 42 import java.time.ZoneId; 43 44 public class TestZoneInfo310 { 45 46 public static void main(String[] args) throws Throwable { 47 48 String TESTDIR = System.getProperty("test.dir", "."); 49 Path tzdir = Paths.get(System.getProperty("test.root"), 50 "..", "..", "make", "data", "tzdata"); 51 String tzfiles = "africa antarctica asia australasia europe northamerica pacificnew southamerica backward etcetera systemv gmt jdk11_backward"; 52 String zidir = TESTDIR + File.separator + "zi"; 53 File fZidir = new File(zidir); 54 if (!fZidir.exists()) { 55 fZidir.mkdirs(); 56 } 57 Matcher m = Pattern.compile("tzdata(?<ver>[0-9]{4}[A-z])") 58 .matcher(new String(Files.readAllBytes(tzdir.resolve("VERSION")), "ascii")); 59 String ver = m.find() ? m.group("ver") : "NULL"; 60 61 ArrayList<String> alist = new ArrayList<>(); 62 alist.add("-V"); 63 alist.add(ver); 64 alist.add("-d"); 65 alist.add(zidir); 66 for (String f : tzfiles.split(" ")) { 67 alist.add(tzdir.resolve(f).toString()); 68 } 69 System.out.println("Compiling tz files!"); 70 Main.main(alist.toArray(new String[alist.size()])); 71 72 ////////////////////////////////// 73 System.out.println("testing!"); 74 ZoneInfoFile.ziDir = zidir; 75 long t0, t1; 76 77 t0 = System.nanoTime(); 78 ZoneInfoOld.getTimeZone("America/Los_Angeles"); 79 t1 = System.nanoTime(); 80 System.out.printf("OLD.getZoneInfoOld()[1]=%d%n", (t1 - t0) / 1000); 81 82 t0 = System.nanoTime(); 83 ZoneInfoOld.getTimeZone("America/New_York"); 84 t1 = System.nanoTime(); 85 System.out.printf("OLD.getZoneInfoOld()[2]=%d%n", (t1 - t0) / 1000); 86 87 t0 = System.nanoTime(); 88 ZoneInfoOld.getTimeZone("America/Denver"); 89 t1 = System.nanoTime(); 90 System.out.printf("OLD.getZoneInfoOld()[3]=%d%n", (t1 - t0) / 1000); 91 92 t0 = System.nanoTime(); 93 String[] zids_old = ZoneInfoOld.getAvailableIDs(); 94 t1 = System.nanoTime(); 95 System.out.printf("OLD.getAvailableIDs()=%d, total=%d%n", 96 (t1 - t0) / 1000, zids_old.length); 97 Arrays.sort(zids_old); 98 99 t0 = System.nanoTime(); 100 String[] alias_old = ZoneInfoOld.getAliasTable() 101 .keySet().toArray(new String[0]); 102 t1 = System.nanoTime(); 103 System.out.printf("OLD.getAliasTable()=%d, total=%d%n", 104 (t1 - t0) / 1000, alias_old.length); 105 Arrays.sort(alias_old); 106 107 t0 = System.currentTimeMillis(); 108 for (String zid : zids_old) { 109 ZoneInfoOld.getTimeZone(zid); 110 } 111 t1 = System.currentTimeMillis(); 112 System.out.printf("OLD.TotalTZ()=%d (ms)%n", t1 - t0); 113 114 /* 115 t0 = System.nanoTime(); 116 ZoneId.of("America/Los_Angeles").getRules(); 117 t1 = System.nanoTime(); 118 System.out.printf("NEW.ZoneId.of()[1]=%d%n", (t1 - t0) / 1000); 119 */ 120 t0 = System.nanoTime(); 121 TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles"); 122 t1 = System.nanoTime(); 123 System.out.printf("NEW.getTimeZone()[1]=%d%n", (t1 - t0) / 1000); 124 125 t0 = System.nanoTime(); 126 tz = TimeZone.getTimeZone("America/New_York"); 127 t1 = System.nanoTime(); 128 System.out.printf("NEW.getTimeZone()[2]=%d%n", (t1 - t0) / 1000); 129 130 t0 = System.nanoTime(); 131 tz = TimeZone.getTimeZone("America/Denver"); 132 t1 = System.nanoTime(); 133 System.out.printf("NEW.getTimeZone()[3]=%d%n", (t1 - t0) / 1000); 134 135 t0 = System.nanoTime(); 136 String[] zids_new = TimeZone.getAvailableIDs(); 137 t1 = System.nanoTime(); 138 System.out.printf("NEW.getAvailableIDs()=%d, total=%d%n", 139 (t1 - t0) / 1000, zids_new.length); 140 Arrays.sort(zids_new); 141 142 t0 = System.nanoTime(); 143 String[] alias_new = sun.util.calendar.ZoneInfo.getAliasTable() 144 .keySet().toArray(new String[0]); 145 t1 = System.nanoTime(); 146 System.out.printf("NEW.getAliasTable()=%d, total=%d%n", 147 (t1 - t0) / 1000, alias_new.length); 148 Arrays.sort(alias_new); 149 150 t0 = System.currentTimeMillis(); 151 for (String zid : zids_new) { 152 TimeZone.getTimeZone(zid); 153 } 154 t1 = System.currentTimeMillis(); 155 System.out.printf("NEW.TotalTZ()=%d (ms)%n", t1 - t0); 156 157 if (!Arrays.equals(zids_old, zids_new)) { 158 throw new RuntimeException(" FAILED: availableIds don't match"); 159 } 160 161 if (!Arrays.equals(alias_old, alias_new)) { 162 throw new RuntimeException(" FAILED: aliases don't match"); 163 } 164 165 for (String zid : zids_new) { 166 ZoneInfoOld zi = toZoneInfoOld(TimeZone.getTimeZone(zid)); 167 ZoneInfoOld ziOLD = (ZoneInfoOld)ZoneInfoOld.getTimeZone(zid); 168 /* 169 * Temporary ignoring the failing TimeZones which are having zone 170 * rules defined till year 2037 and/or above and have negative DST 171 * save time in IANA tzdata. This bug is tracked via JDK-8223388. 172 * 173 * These are the zones/rules that employ negative DST in vanguard 174 * format (as of 2019a): 175 * 176 * - Rule "Eire" 177 * - Rule "Morocco" 178 * - Rule "Namibia" 179 * - Zone "Europe/Prague" 180 * 181 * Tehran/Iran rule has rules beyond 2037, in which javazic assumes 182 * to be the last year. Thus javazic's rule is based on year 2037 183 * (Mar 20th/Sep 20th are the cutover dates), while the real rule 184 * has year 2087 where Mar 21st/Sep 21st are the cutover dates. 185 */ 186 if (zid.equals("Africa/Casablanca") || // uses "Morocco" rule 187 zid.equals("Africa/El_Aaiun") || // uses "Morocco" rule 188 zid.equals("Africa/Windhoek") || // uses "Namibia" rule 189 zid.equals("Eire") || 190 zid.equals("Europe/Bratislava") || // link to "Europe/Prague" 191 zid.equals("Europe/Dublin") || // uses "Eire" rule 192 zid.equals("Europe/Prague") || 193 zid.equals("Asia/Tehran") || // last rule mismatch 194 zid.equals("Iran")) { // last rule mismatch 195 continue; 196 } 197 if (! zi.equalsTo(ziOLD)) { 198 System.out.println(zi.diffsTo(ziOLD)); 199 throw new RuntimeException(" FAILED: " + zid); 200 } 201 } 202 delete(fZidir); 203 204 // test tzdb version 205 if (!ver.equals(sun.util.calendar.ZoneInfoFile.getVersion())) { 206 System.out.printf(" FAILED: ver=%s, expected=%s%n", 207 sun.util.calendar.ZoneInfoFile.getVersion(), ver); 208 throw new RuntimeException("Version test failed"); 209 } 210 211 // test getAvailableIDs(raw); 212 zids_new = TimeZone.getAvailableIDs(-8 * 60 * 60 * 1000); 213 //Arrays.sort(zids_new); 214 zids_old = ZoneInfoOld.getAvailableIDs(-8 * 60 * 60 * 1000); 215 if (!Arrays.equals(zids_new, zids_old)) { 216 System.out.println("------------------------"); 217 System.out.println("NEW.getAvailableIDs(-8:00)"); 218 for (String zid : zids_new) { 219 System.out.println(zid); 220 } 221 System.out.println("------------------------"); 222 System.out.println("OLD.getAvailableIDs(-8:00)"); 223 for (String zid : zids_old) { 224 System.out.println(zid); 225 } 226 throw new RuntimeException(" FAILED: availableIds(offset) don't match"); 227 } 228 } 229 230 private static void delete(File f) { 231 if (f.isDirectory()) { 232 for (File f0 : f.listFiles()) { 233 delete(f0); 234 } 235 } 236 f.delete(); 237 } 238 239 // to access sun.util.calendar.ZoneInfo's private fields 240 static Class<?> ziClz; 241 static Field rawOffset; 242 static Field checksum; 243 static Field dstSavings; 244 static Field transitions; 245 static Field offsets; 246 static Field simpleTimeZoneParams; 247 static Field willGMTOffsetChange; 248 static { 249 try { 250 ziClz = Class.forName("sun.util.calendar.ZoneInfo"); 251 rawOffset = ziClz.getDeclaredField("rawOffset"); 252 checksum = ziClz.getDeclaredField("checksum"); 253 dstSavings = ziClz.getDeclaredField("dstSavings"); 254 transitions = ziClz.getDeclaredField("transitions"); 255 offsets = ziClz.getDeclaredField("offsets"); 256 simpleTimeZoneParams = ziClz.getDeclaredField("simpleTimeZoneParams"); 257 willGMTOffsetChange = ziClz.getDeclaredField("willGMTOffsetChange"); 258 rawOffset.setAccessible(true); 259 checksum.setAccessible(true); 260 dstSavings.setAccessible(true); 261 transitions.setAccessible(true); 262 offsets.setAccessible(true); 263 simpleTimeZoneParams.setAccessible(true); 264 willGMTOffsetChange.setAccessible(true); 265 } catch (Exception x) { 266 throw new RuntimeException(x); 267 } 268 } 269 270 private static ZoneInfoOld toZoneInfoOld(TimeZone tz) throws Exception { 271 return new ZoneInfoOld(tz.getID(), 272 rawOffset.getInt(tz), 273 dstSavings.getInt(tz), 274 checksum.getInt(tz), 275 (long[])transitions.get(tz), 276 (int[])offsets.get(tz), 277 (int[])simpleTimeZoneParams.get(tz), 278 willGMTOffsetChange.getBoolean(tz)); 279 } 280 281 282 }