| /* | |
| * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. | |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| * | |
| * This code is free software; you can redistribute it and/or modify it | |
| * under the terms of the GNU General Public License version 2 only, as | |
| * published by the Free Software Foundation. | |
| * | |
| * This code is distributed in the hope that it will be useful, but WITHOUT | |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| * version 2 for more details (a copy is included in the LICENSE file that | |
| * accompanied this code). | |
| * | |
| * You should have received a copy of the GNU General Public License version | |
| * 2 along with this work; if not, write to the Free Software Foundation, | |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| * | |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| * or visit www.oracle.com if you need additional information or have any | |
| * questions. | |
| */ | |
| /* | |
| * @test | |
| * @bug 4028006 4044013 4096694 4107276 4107570 4112869 4130885 7039469 7126465 7158483 | |
| * 8008577 8077685 8098547 8133321 8138716 8148446 8151876 8159684 8166875 8181157 | |
| * 8228469 8274407 8285844 8305113 8174269 | |
| * @modules java.base/sun.util.resources | |
| * @summary test TimeZone | |
| * @run junit TimeZoneTest | |
| */ | |
| import java.io.*; | |
| import java.text.*; | |
| import java.util.*; | |
| import sun.util.resources.LocaleData; | |
| import org.junit.jupiter.api.Test; | |
| import static org.junit.jupiter.api.Assertions.fail; | |
| public class TimeZoneTest | |
| { | |
| static final int millisPerHour = 3600000; | |
| /** | |
| * Bug 4130885 | |
| * Certain short zone IDs, used since 1.1.x, are incorrect. | |
| * | |
| * The worst of these is: | |
| * | |
| * "CAT" (Central African Time) should be GMT+2:00, but instead returns a | |
| * zone at GMT-1:00. The zone at GMT-1:00 should be called EGT, CVT, EGST, | |
| * or AZOST, depending on which zone is meant, but in no case is it CAT. | |
| * | |
| * Other wrong zone IDs: | |
| * | |
| * ECT (European Central Time) GMT+1:00: ECT is Ecuador Time, | |
| * GMT-5:00. European Central time is abbreviated CEST. | |
| * | |
| * SST (Solomon Island Time) GMT+11:00. SST is actually Samoa Standard Time, | |
| * GMT-11:00. Solomon Island time is SBT. | |
| * | |
| * NST (New Zealand Time) GMT+12:00. NST is the abbreviation for | |
| * Newfoundland Standard Time, GMT-3:30. New Zealanders use NZST. | |
| * | |
| * AST (Alaska Standard Time) GMT-9:00. [This has already been noted in | |
| * another bug.] It should be "AKST". AST is Atlantic Standard Time, | |
| * GMT-4:00. | |
| * | |
| * PNT (Phoenix Time) GMT-7:00. PNT usually means Pitcairn Time, | |
| * GMT-8:30. There is no standard abbreviation for Phoenix time, as distinct | |
| * from MST with daylight savings. | |
| * | |
| * In addition to these problems, a number of zones are FAKE. That is, they | |
| * don't match what people use in the real world. | |
| * | |
| * FAKE zones: | |
| * | |
| * EET (should be EEST) | |
| * ART (should be EET) | |
| * MET (should be IRST) | |
| * NET (should be AMST) | |
| * PLT (should be PKT) | |
| * BST (should be BDT) | |
| * VST (should be ICT) | |
| * CTT (should be CST) + | |
| * ACT (should be CST) + | |
| * AET (should be EST) + | |
| * MIT (should be WST) + | |
| * IET (should be EST) + | |
| * PRT (should be AST) + | |
| * CNT (should be NST) | |
| * AGT (should be ARST) | |
| * BET (should be EST) + | |
| * | |
| * + A zone with the correct name already exists and means something | |
| * else. E.g., EST usually indicates the US Eastern zone, so it cannot be | |
| * used for Brazil (BET). | |
| */ | |
| @Test | |
| public void TestShortZoneIDs() throws Exception { | |
| ZoneDescriptor[] JDK_116_REFERENCE_LIST = { | |
| new ZoneDescriptor("MIT", 780, false), // Samoa no longer observes DST starting 2021b | |
| new ZoneDescriptor("HST", -600, false), | |
| new ZoneDescriptor("AST", -540, true), | |
| new ZoneDescriptor("PST", -480, true), | |
| new ZoneDescriptor("PNT", -420, false), | |
| new ZoneDescriptor("MST", -420, false), | |
| new ZoneDescriptor("CST", -360, true), | |
| new ZoneDescriptor("IET", -300, true), | |
| new ZoneDescriptor("EST", -300, false), | |
| new ZoneDescriptor("PRT", -240, false), | |
| new ZoneDescriptor("CNT", -210, true), | |
| new ZoneDescriptor("AGT", -180, false), | |
| new ZoneDescriptor("BET", -180, false), | |
| // new ZoneDescriptor("CAT", -60, false), // Wrong: | |
| // As of bug 4130885, fix CAT (Central Africa) | |
| new ZoneDescriptor("CAT", 120, false), // Africa/Harare | |
| new ZoneDescriptor("GMT", 0, false), | |
| new ZoneDescriptor("UTC", 0, false), | |
| new ZoneDescriptor("ECT", 60, true), | |
| new ZoneDescriptor("ART", 120, true), | |
| new ZoneDescriptor("EET", 120, true), | |
| new ZoneDescriptor("EAT", 180, false), | |
| new ZoneDescriptor("MET", 60, true), | |
| new ZoneDescriptor("NET", 240, false), | |
| new ZoneDescriptor("PLT", 300, false), | |
| new ZoneDescriptor("IST", 330, false), | |
| new ZoneDescriptor("BST", 360, false), | |
| new ZoneDescriptor("VST", 420, false), | |
| new ZoneDescriptor("CTT", 480, false), | |
| new ZoneDescriptor("JST", 540, false), | |
| new ZoneDescriptor("ACT", 570, false), | |
| new ZoneDescriptor("AET", 600, true), | |
| new ZoneDescriptor("SST", 660, false), | |
| // new ZoneDescriptor("NST", 720, false), | |
| // As of bug 4130885, fix NST (New Zealand) | |
| new ZoneDescriptor("NST", 720, true), // Pacific/Auckland | |
| }; | |
| Map<String, ZoneDescriptor> hash = new HashMap<>(); | |
| String[] ids = TimeZone.getAvailableIDs(); | |
| for (String id : ids) { | |
| if (id.length() == 3) { | |
| hash.put(id, new ZoneDescriptor(TimeZone.getTimeZone(id))); | |
| } | |
| } | |
| for (int i = 0; i < JDK_116_REFERENCE_LIST.length; ++i) { | |
| ZoneDescriptor referenceZone = JDK_116_REFERENCE_LIST[i]; | |
| ZoneDescriptor currentZone = hash.get(referenceZone.getID()); | |
| if (referenceZone.equals(currentZone)) { | |
| System.out.println("ok " + referenceZone); | |
| } | |
| else { | |
| fail("Fail: Expected " + referenceZone + | |
| "; got " + currentZone); | |
| } | |
| } | |
| } | |
| /** | |
| * A descriptor for a zone; used to regress the short zone IDs. | |
| */ | |
| static class ZoneDescriptor { | |
| String id; | |
| int offset; // In minutes | |
| boolean daylight; | |
| ZoneDescriptor(TimeZone zone) { | |
| this.id = zone.getID(); | |
| this.offset = zone.getRawOffset() / 60000; | |
| this.daylight = zone.useDaylightTime(); | |
| } | |
| ZoneDescriptor(String id, int offset, boolean daylight) { | |
| this.id = id; | |
| this.offset = offset; | |
| this.daylight = daylight; | |
| } | |
| public String getID() { return id; } | |
| @Override | |
| public boolean equals(Object o) { | |
| ZoneDescriptor that = (ZoneDescriptor)o; | |
| return that != null && | |
| id.equals(that.id) && | |
| offset == that.offset && | |
| daylight == that.daylight; | |
| } | |
| @Override | |
| public int hashCode() { | |
| return id.hashCode() ^ offset | (daylight ? 1 : 0); | |
| } | |
| @Override | |
| public String toString() { | |
| int min = offset; | |
| char sign = '+'; | |
| if (min < 0) { sign = '-'; min = -min; } | |
| return "Zone[\"" + id + "\", GMT" + sign + (min/60) + ':' + | |
| (min%60<10?"0":"") + (min%60) + ", " + | |
| (daylight ? "Daylight" : "Standard") + "]"; | |
| } | |
| public static int compare(Object o1, Object o2) { | |
| ZoneDescriptor i1 = (ZoneDescriptor)o1; | |
| ZoneDescriptor i2 = (ZoneDescriptor)o2; | |
| if (i1.offset > i2.offset) return 1; | |
| if (i1.offset < i2.offset) return -1; | |
| if (i1.daylight && !i2.daylight) return 1; | |
| if (!i1.daylight && i2.daylight) return -1; | |
| return i1.id.compareTo(i2.id); | |
| } | |
| } | |
| static final String formatSeconds(int sec) { | |
| char sign = '+'; | |
| if (sec < 0) { sign = '-'; sec = -sec; } | |
| int h = sec / 3_600; | |
| int m = sec % 3_600 / 60; | |
| sec = sec % 60; | |
| return "" + sign + h + ":" + ((m<10) ? "0" : "") + m + | |
| (sec > 0 ? ":" + ((sec < 10) ? "0" : "") + sec : ""); | |
| } | |
| /** | |
| * As part of the VM fix (see CCC approved RFE 4028006, bug | |
| * 4044013), TimeZone.getTimeZone() has been modified to recognize | |
| * generic IDs of the form GMT[+-]hh:mm, GMT[+-]hhmm, and | |
| * GMT[+-]hh. Test this behavior here. | |
| * | |
| * Bug 4044013 | |
| * | |
| * ID "Custom" is no longer used for TimeZone objects created with | |
| * a custom time zone ID, such as "GMT-8". See 4322313. | |
| */ | |
| @Test | |
| public void TestCustomParse() throws Exception { | |
| Object[] DATA = { | |
| // ID Expected offset in seconds | |
| "GMT", null, | |
| "GMT+0", 0, | |
| "GMT+1", 60 * 60, | |
| "GMT-0030", -30 * 60, | |
| "GMT+15:99", null, | |
| "GMT+", null, | |
| "GMT-", null, | |
| "GMT+0:", null, | |
| "GMT-:", null, | |
| "GMT+0010", 10 * 60, // Interpret this as 00:10 | |
| "GMT-10", -10 * 60 * 60, | |
| "GMT+30", null, | |
| "GMT-3:30", -(3 * 60 + 30) * 60, | |
| "GMT-230", -(2 * 60 + 30) * 60, | |
| "GMT+00:00:01", 1, | |
| "GMT-00:00:01", -1, | |
| "GMT+00000", null, | |
| "GMT+00:00:01:", null, | |
| "GMT+00:00:012", null, | |
| "GMT+00:00:0", null, | |
| "GMT+00:00:", null, | |
| }; | |
| for (int i=0; i<DATA.length; i+=2) { | |
| String id = (String)DATA[i]; | |
| Integer exp = (Integer)DATA[i+1]; | |
| TimeZone zone = TimeZone.getTimeZone(id); | |
| if (zone.getID().equals("GMT")) { | |
| System.out.println(id + " -> generic GMT"); | |
| // When TimeZone.getTimeZone() can't parse the id, it | |
| // returns GMT -- a dubious practice, but required for | |
| // backward compatibility. | |
| if (exp != null) { | |
| throw new Exception("Expected offset of " + formatSeconds(exp.intValue()) + | |
| " for " + id + ", got parse failure"); | |
| } | |
| } | |
| else { | |
| int ioffset = zone.getRawOffset() / 1_000; | |
| String offset = formatSeconds(ioffset); | |
| System.out.println(id + " -> " + zone.getID() + " GMT" + offset); | |
| if (exp == null) { | |
| throw new Exception("Expected parse failure for " + id + | |
| ", got offset of " + offset + | |
| ", id " + zone.getID()); | |
| } | |
| else if (ioffset != exp.intValue()) { | |
| throw new Exception("Expected offset of " + formatSeconds(exp.intValue()) + | |
| ", id Custom, for " + id + | |
| ", got offset of " + offset + | |
| ", id " + zone.getID()); | |
| } | |
| } | |
| } | |
| } | |
| /** | |
| * Test the basic functionality of the getDisplayName() API. | |
| * | |
| * Bug 4112869 | |
| * Bug 4028006 | |
| * | |
| * See also API change request A41. | |
| * | |
| * 4/21/98 - make smarter, so the test works if the ext resources | |
| * are present or not. | |
| */ | |
| @Test | |
| public void TestDisplayName() { | |
| TimeZone zone = TimeZone.getTimeZone("PST"); | |
| String name = zone.getDisplayName(Locale.ENGLISH); | |
| System.out.println("PST->" + name); | |
| if (!name.equals("Pacific Standard Time")) | |
| fail("Fail: Expected \"Pacific Standard Time\""); | |
| //***************************************************************** | |
| // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES | |
| // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES | |
| // THE FOLLOWING LINES MUST BE UPDATED IF THE LOCALE DATA CHANGES | |
| //***************************************************************** | |
| Object[] DATA = { | |
| new Boolean(false), new Integer(TimeZone.SHORT), "PST", | |
| new Boolean(true), new Integer(TimeZone.SHORT), "PDT", | |
| new Boolean(false), new Integer(TimeZone.LONG), "Pacific Standard Time", | |
| new Boolean(true), new Integer(TimeZone.LONG), "Pacific Daylight Time", | |
| }; | |
| for (int i=0; i<DATA.length; i+=3) { | |
| name = zone.getDisplayName(((Boolean)DATA[i]).booleanValue(), | |
| ((Integer)DATA[i+1]).intValue(), | |
| Locale.ENGLISH); | |
| if (!name.equals(DATA[i+2])) | |
| fail("Fail: Expected " + DATA[i+2] + "; got " + name); | |
| } | |
| // Make sure that we don't display the DST name by constructing a fake | |
| // PST zone that has DST all year long. | |
| SimpleTimeZone zone2 = new SimpleTimeZone(0, "PST"); | |
| zone2.setStartRule(Calendar.JANUARY, 1, 0); | |
| zone2.setEndRule(Calendar.DECEMBER, 31, 0); | |
| System.out.println("Modified PST inDaylightTime->" + zone2.inDaylightTime(new Date())); | |
| name = zone2.getDisplayName(Locale.ENGLISH); | |
| System.out.println("Modified PST->" + name); | |
| if (!name.equals("Pacific Standard Time")) | |
| fail("Fail: Expected \"Pacific Standard Time\""); | |
| // Make sure we get the default display format for Locales | |
| // with no display name data. | |
| Locale zh_CN = Locale.SIMPLIFIED_CHINESE; | |
| name = zone.getDisplayName(zh_CN); | |
| //***************************************************************** | |
| // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES | |
| // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES | |
| // THE FOLLOWING LINE MUST BE UPDATED IF THE LOCALE DATA CHANGES | |
| //***************************************************************** | |
| System.out.println("PST(zh_CN)->" + name); | |
| // Now be smart -- check to see if zh resource is even present. | |
| // If not, we expect the en fallback behavior. | |
| ResourceBundle enRB = LocaleData.getBundle("sun.util.resources.cldr.TimeZoneNames", | |
| Locale.ENGLISH); | |
| ResourceBundle zhRB = LocaleData.getBundle("sun.util.resources.cldr.TimeZoneNames", | |
| zh_CN); | |
| boolean noZH = enRB == zhRB; | |
| if (noZH) { | |
| System.out.println("Warning: Not testing the zh_CN behavior because resource is absent"); | |
| if (!name.equals("Pacific Standard Time")) | |
| fail("Fail: Expected Pacific Standard Time"); | |
| } | |
| else if (!name.equals("Pacific Standard Time") && | |
| !name.equals("\u592a\u5e73\u6d0b\u6807\u51c6\u65f6\u95f4") && | |
| !name.equals("\u5317\u7f8e\u592a\u5e73\u6d0b\u6807\u51c6\u65f6\u95f4") && | |
| !name.equals("GMT-08:00") && | |
| !name.equals("GMT-8:00") && | |
| !name.equals("GMT-0800") && | |
| !name.equals("GMT-800")) { | |
| fail("Fail: Expected GMT-08:00 or something similar\n" | |
| + "************************************************************\n" | |
| + "THE ABOVE FAILURE MAY JUST MEAN THE LOCALE DATA HAS CHANGED\n" | |
| + "************************************************************\n"); | |
| } | |
| // Now try a non-existent zone | |
| zone2 = new SimpleTimeZone(90*60*1000, "xyzzy"); | |
| name = zone2.getDisplayName(Locale.ENGLISH); | |
| System.out.println("GMT+90min->" + name); | |
| if (!name.equals("GMT+01:30") && | |
| !name.equals("GMT+1:30") && | |
| !name.equals("GMT+0130") && | |
| !name.equals("GMT+130")) | |
| fail("Fail: Expected GMT+01:30 or something similar"); | |
| } | |
| @Test | |
| public void TestGenericAPI() { | |
| String id = "NewGMT"; | |
| int offset = 12345; | |
| SimpleTimeZone zone = new SimpleTimeZone(offset, id); | |
| if (zone.useDaylightTime()) { | |
| fail("FAIL: useDaylightTime should return false"); | |
| } | |
| TimeZone zoneclone = (TimeZone)zone.clone(); | |
| if (!zoneclone.equals(zone)) { | |
| fail("FAIL: clone or operator== failed"); | |
| } | |
| zoneclone.setID("abc"); | |
| if (zoneclone.equals(zone)) { | |
| fail("FAIL: clone or operator!= failed"); | |
| } | |
| zoneclone = (TimeZone)zone.clone(); | |
| if (!zoneclone.equals(zone)) { | |
| fail("FAIL: clone or operator== failed"); | |
| } | |
| zoneclone.setRawOffset(45678); | |
| if (zoneclone.equals(zone)) { | |
| fail("FAIL: clone or operator!= failed"); | |
| } | |
| TimeZone saveDefault = TimeZone.getDefault(); | |
| try { | |
| TimeZone.setDefault(zone); | |
| TimeZone defaultzone = TimeZone.getDefault(); | |
| if (defaultzone == zone) { | |
| fail("FAIL: Default object is identical, not clone"); | |
| } | |
| if (!defaultzone.equals(zone)) { | |
| fail("FAIL: Default object is not equal"); | |
| } | |
| } | |
| finally { | |
| TimeZone.setDefault(saveDefault); | |
| } | |
| } | |
| @SuppressWarnings("deprecation") | |
| @Test | |
| public void TestRuleAPI() | |
| { | |
| // ErrorCode status = ZERO_ERROR; | |
| int offset = (int)(60*60*1000*1.75); // Pick a weird offset | |
| SimpleTimeZone zone = new SimpleTimeZone(offset, "TestZone"); | |
| if (zone.useDaylightTime()) fail("FAIL: useDaylightTime should return false"); | |
| // Establish our expected transition times. Do this with a non-DST | |
| // calendar with the (above) declared local offset. | |
| GregorianCalendar gc = new GregorianCalendar(zone); | |
| gc.clear(); | |
| gc.set(1990, Calendar.MARCH, 1); | |
| long marchOneStd = gc.getTime().getTime(); // Local Std time midnight | |
| gc.clear(); | |
| gc.set(1990, Calendar.JULY, 1); | |
| long julyOneStd = gc.getTime().getTime(); // Local Std time midnight | |
| // Starting and ending hours, WALL TIME | |
| int startHour = (int)(2.25 * 3600000); | |
| int endHour = (int)(3.5 * 3600000); | |
| zone.setStartRule(Calendar.MARCH, 1, 0, startHour); | |
| zone.setEndRule (Calendar.JULY, 1, 0, endHour); | |
| gc = new GregorianCalendar(zone); | |
| // if (failure(status, "new GregorianCalendar")) return; | |
| long marchOne = marchOneStd + startHour; | |
| long julyOne = julyOneStd + endHour - 3600000; // Adjust from wall to Std time | |
| long expMarchOne = 636251400000L; | |
| if (marchOne != expMarchOne) | |
| { | |
| fail("FAIL: Expected start computed as " + marchOne + | |
| " = " + new Date(marchOne)); | |
| System.out.println(" Should be " + expMarchOne + | |
| " = " + new Date(expMarchOne)); | |
| } | |
| long expJulyOne = 646793100000L; | |
| if (julyOne != expJulyOne) | |
| { | |
| fail("FAIL: Expected start computed as " + julyOne + | |
| " = " + new Date(julyOne)); | |
| System.out.println(" Should be " + expJulyOne + | |
| " = " + new Date(expJulyOne)); | |
| } | |
| testUsingBinarySearch(zone, new Date(90, Calendar.JANUARY, 1).getTime(), | |
| new Date(90, Calendar.JUNE, 15).getTime(), marchOne); | |
| testUsingBinarySearch(zone, new Date(90, Calendar.JUNE, 1).getTime(), | |
| new Date(90, Calendar.DECEMBER, 31).getTime(), julyOne); | |
| if (zone.inDaylightTime(new Date(marchOne - 1000)) || | |
| !zone.inDaylightTime(new Date(marchOne))) | |
| fail("FAIL: Start rule broken"); | |
| if (!zone.inDaylightTime(new Date(julyOne - 1000)) || | |
| zone.inDaylightTime(new Date(julyOne))) | |
| fail("FAIL: End rule broken"); | |
| zone.setStartYear(1991); | |
| if (zone.inDaylightTime(new Date(marchOne)) || | |
| zone.inDaylightTime(new Date(julyOne - 1000))) | |
| fail("FAIL: Start year broken"); | |
| // failure(status, "TestRuleAPI"); | |
| // delete gc; | |
| // delete zone; | |
| } | |
| void testUsingBinarySearch(SimpleTimeZone tz, long min, long max, long expectedBoundary) | |
| { | |
| // ErrorCode status = ZERO_ERROR; | |
| boolean startsInDST = tz.inDaylightTime(new Date(min)); | |
| // if (failure(status, "SimpleTimeZone::inDaylightTime")) return; | |
| if (tz.inDaylightTime(new Date(max)) == startsInDST) { | |
| System.out.println("Error: inDaylightTime(" + new Date(max) + ") != " + (!startsInDST)); | |
| return; | |
| } | |
| // if (failure(status, "SimpleTimeZone::inDaylightTime")) return; | |
| while ((max - min) > INTERVAL) { | |
| long mid = (min + max) / 2; | |
| if (tz.inDaylightTime(new Date(mid)) == startsInDST) { | |
| min = mid; | |
| } | |
| else { | |
| max = mid; | |
| } | |
| // if (failure(status, "SimpleTimeZone::inDaylightTime")) return; | |
| } | |
| System.out.println("Binary Search Before: " + min + " = " + new Date(min)); | |
| System.out.println("Binary Search After: " + max + " = " + new Date(max)); | |
| long mindelta = expectedBoundary - min; | |
| long maxdelta = max - expectedBoundary; | |
| if (mindelta >= 0 && | |
| mindelta <= INTERVAL && | |
| mindelta >= 0 && | |
| mindelta <= INTERVAL) | |
| System.out.println("PASS: Expected bdry: " + expectedBoundary + " = " + new Date(expectedBoundary)); | |
| else | |
| fail("FAIL: Expected bdry: " + expectedBoundary + " = " + new Date(expectedBoundary)); | |
| } | |
| static final int INTERVAL = 100; | |
| // Bug 006; verify the offset for a specific zone. | |
| @Test | |
| public void TestPRTOffset() | |
| { | |
| TimeZone tz = TimeZone.getTimeZone( "PRT" ); | |
| if( tz == null ) { | |
| fail( "FAIL: TimeZone(PRT) is null" ); | |
| } | |
| else{ | |
| if (tz.getRawOffset() != (-4*millisPerHour)) | |
| fail("FAIL: Offset for PRT should be -4"); | |
| } | |
| } | |
| // Test various calls | |
| @SuppressWarnings("deprecation") | |
| @Test | |
| public void TestVariousAPI518() | |
| { | |
| TimeZone time_zone = TimeZone.getTimeZone("PST"); | |
| Date d = new Date(97, Calendar.APRIL, 30); | |
| System.out.println("The timezone is " + time_zone.getID()); | |
| if (time_zone.inDaylightTime(d) != true) | |
| fail("FAIL: inDaylightTime returned false"); | |
| if (time_zone.useDaylightTime() != true) | |
| fail("FAIL: useDaylightTime returned false"); | |
| if (time_zone.getRawOffset() != -8*millisPerHour) | |
| fail( "FAIL: getRawOffset returned wrong value"); | |
| GregorianCalendar gc = new GregorianCalendar(); | |
| gc.setTime(d); | |
| if (time_zone.getOffset(gc.AD, gc.get(gc.YEAR), gc.get(gc.MONTH), | |
| gc.get(gc.DAY_OF_MONTH), | |
| gc.get(gc.DAY_OF_WEEK), 0) | |
| != -7*millisPerHour) | |
| fail("FAIL: getOffset returned wrong value"); | |
| } | |
| // Test getAvailableID API | |
| @Test | |
| public void TestGetAvailableIDs913() | |
| { | |
| StringBuffer buf = new StringBuffer("TimeZone.getAvailableIDs() = { "); | |
| String[] s = TimeZone.getAvailableIDs(); | |
| for (int i=0; i<s.length; ++i) | |
| { | |
| if (i > 0) buf.append(", "); | |
| buf.append(s[i]); | |
| } | |
| buf.append(" };"); | |
| System.out.println(buf.toString()); | |
| buf.setLength(0); | |
| buf.append("TimeZone.getAvailableIDs(GMT+02:00) = { "); | |
| s = TimeZone.getAvailableIDs(+2 * 60 * 60 * 1000); | |
| for (int i=0; i<s.length; ++i) | |
| { | |
| if (i > 0) buf.append(", "); | |
| buf.append(s[i]); | |
| } | |
| buf.append(" };"); | |
| System.out.println(buf.toString()); | |
| TimeZone tz = TimeZone.getTimeZone("PST"); | |
| if (tz != null) | |
| System.out.println("getTimeZone(PST) = " + tz.getID()); | |
| else | |
| fail("FAIL: getTimeZone(PST) = null"); | |
| tz = TimeZone.getTimeZone("America/Los_Angeles"); | |
| if (tz != null) | |
| System.out.println("getTimeZone(America/Los_Angeles) = " + tz.getID()); | |
| else | |
| fail("FAIL: getTimeZone(PST) = null"); | |
| // Bug 4096694 | |
| tz = TimeZone.getTimeZone("NON_EXISTENT"); | |
| if (tz == null) | |
| fail("FAIL: getTimeZone(NON_EXISTENT) = null"); | |
| else if (!tz.getID().equals("GMT")) | |
| fail("FAIL: getTimeZone(NON_EXISTENT) = " + tz.getID()); | |
| } | |
| /** | |
| * Bug 4107276 | |
| */ | |
| @Test | |
| public void TestDSTSavings() { | |
| // It might be better to find a way to integrate this test into the main TimeZone | |
| // tests above, but I don't have time to figure out how to do this (or if it's | |
| // even really a good idea). Let's consider that a future. --rtg 1/27/98 | |
| SimpleTimeZone tz = new SimpleTimeZone(-5 * millisPerHour, "dstSavingsTest", | |
| Calendar.MARCH, 1, 0, 0, Calendar.SEPTEMBER, 1, 0, 0, | |
| (int)(0.5 * millisPerHour)); | |
| if (tz.getRawOffset() != -5 * millisPerHour) | |
| fail("Got back a raw offset of " + (tz.getRawOffset() / millisPerHour) + | |
| " hours instead of -5 hours."); | |
| if (!tz.useDaylightTime()) | |
| fail("Test time zone should use DST but claims it doesn't."); | |
| if (tz.getDSTSavings() != 0.5 * millisPerHour) | |
| fail("Set DST offset to 0.5 hour, but got back " + (tz.getDSTSavings() / | |
| millisPerHour) + " hours instead."); | |
| int offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JANUARY, 1, | |
| Calendar.THURSDAY, 10 * millisPerHour); | |
| if (offset != -5 * millisPerHour) | |
| fail("The offset for 10 AM, 1/1/98 should have been -5 hours, but we got " | |
| + (offset / millisPerHour) + " hours."); | |
| offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JUNE, 1, Calendar.MONDAY, | |
| 10 * millisPerHour); | |
| if (offset != -4.5 * millisPerHour) | |
| fail("The offset for 10 AM, 6/1/98 should have been -4.5 hours, but we got " | |
| + (offset / millisPerHour) + " hours."); | |
| tz.setDSTSavings(millisPerHour); | |
| offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JANUARY, 1, | |
| Calendar.THURSDAY, 10 * millisPerHour); | |
| if (offset != -5 * millisPerHour) | |
| fail("The offset for 10 AM, 1/1/98 should have been -5 hours, but we got " | |
| + (offset / millisPerHour) + " hours."); | |
| offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.JUNE, 1, Calendar.MONDAY, | |
| 10 * millisPerHour); | |
| if (offset != -4 * millisPerHour) | |
| fail("The offset for 10 AM, 6/1/98 (with a 1-hour DST offset) should have been -4 hours, but we got " | |
| + (offset / millisPerHour) + " hours."); | |
| } | |
| /** | |
| * Bug 4107570 | |
| */ | |
| @Test | |
| public void TestAlternateRules() { | |
| // Like TestDSTSavings, this test should probably be integrated somehow with the main | |
| // test at the top of this class, but I didn't have time to figure out how to do that. | |
| // --rtg 1/28/98 | |
| SimpleTimeZone tz = new SimpleTimeZone(-5 * millisPerHour, "alternateRuleTest"); | |
| // test the day-of-month API | |
| tz.setStartRule(Calendar.MARCH, 10, 12 * millisPerHour); | |
| tz.setEndRule(Calendar.OCTOBER, 20, 12 * millisPerHour); | |
| int offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 5, | |
| Calendar.THURSDAY, 10 * millisPerHour); | |
| if (offset != -5 * millisPerHour) | |
| fail("The offset for 10AM, 3/5/98 should have been -5 hours, but we got " | |
| + (offset / millisPerHour) + " hours."); | |
| offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 15, | |
| Calendar.SUNDAY, 10 * millisPerHour); | |
| if (offset != -4 * millisPerHour) | |
| fail("The offset for 10AM, 3/15/98 should have been -4 hours, but we got " | |
| + (offset / millisPerHour) + " hours."); | |
| offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 15, | |
| Calendar.THURSDAY, 10 * millisPerHour); | |
| if (offset != -4 * millisPerHour) | |
| fail("The offset for 10AM, 10/15/98 should have been -4 hours, but we got " | |
| + (offset / millisPerHour) + " hours."); | |
| offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 25, | |
| Calendar.SUNDAY, 10 * millisPerHour); | |
| if (offset != -5 * millisPerHour) | |
| fail("The offset for 10AM, 10/25/98 should have been -5 hours, but we got " | |
| + (offset / millisPerHour) + " hours."); | |
| // test the day-of-week-after-day-in-month API | |
| tz.setStartRule(Calendar.MARCH, 10, Calendar.FRIDAY, 12 * millisPerHour, true); | |
| tz.setEndRule(Calendar.OCTOBER, 20, Calendar.FRIDAY, 12 * millisPerHour, false); | |
| offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 11, | |
| Calendar.WEDNESDAY, 10 * millisPerHour); | |
| if (offset != -5 * millisPerHour) | |
| fail("The offset for 10AM, 3/11/98 should have been -5 hours, but we got " | |
| + (offset / millisPerHour) + " hours."); | |
| offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.MARCH, 14, | |
| Calendar.SATURDAY, 10 * millisPerHour); | |
| if (offset != -4 * millisPerHour) | |
| fail("The offset for 10AM, 3/14/98 should have been -4 hours, but we got " | |
| + (offset / millisPerHour) + " hours."); | |
| offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 15, | |
| Calendar.THURSDAY, 10 * millisPerHour); | |
| if (offset != -4 * millisPerHour) | |
| fail("The offset for 10AM, 10/15/98 should have been -4 hours, but we got " | |
| + (offset / millisPerHour) + " hours."); | |
| offset = tz.getOffset(GregorianCalendar.AD, 1998, Calendar.OCTOBER, 17, | |
| Calendar.SATURDAY, 10 * millisPerHour); | |
| if (offset != -5 * millisPerHour) | |
| fail("The offset for 10AM, 10/17/98 should have been -5 hours, but we got " | |
| + (offset / millisPerHour) + " hours."); | |
| } | |
| } | |
| //eof |