/* * Copyright (c) 1998, 2016, 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 4052967 4073209 4073215 4084933 4096952 4109314 4126678 4151406 4151429 * 4154525 4154537 4154542 4154650 4159922 4162593 4173604 4176686 4184229 4208960 * 4966229 6433179 6851214 8007520 8008577 * @library /java/text/testlib * @run main/othervm -Djava.locale.providers=COMPAT,SPI TimeZoneRegression */ import java.util.*; import java.io.*; import java.text.*; public class TimeZoneRegression extends IntlTest { public static void main(String[] args) throws Exception { new TimeZoneRegression().run(args); } public void Test4073209() { TimeZone z1 = TimeZone.getTimeZone("PST"); TimeZone z2 = TimeZone.getTimeZone("PST"); if (z1 == z2) { errln("Fail: TimeZone should return clones"); } } @SuppressWarnings("deprecation") public void Test4073215() { SimpleTimeZone z = new SimpleTimeZone(0, "GMT"); if (z.useDaylightTime()) { errln("Fail: Fix test to start with non-DST zone"); } z.setStartRule(Calendar.FEBRUARY, 1, Calendar.SUNDAY, 0); z.setEndRule(Calendar.MARCH, -1, Calendar.SUNDAY, 0); if (!z.useDaylightTime()) { errln("Fail: DST not active"); } if (z.inDaylightTime(new Date(97, Calendar.JANUARY, 31)) || !z.inDaylightTime(new Date(97, Calendar.MARCH, 1)) || z.inDaylightTime(new Date(97, Calendar.MARCH, 31))) { errln("Fail: DST not working as expected"); } } /** * The expected behavior of TimeZone around the boundaries is: * (Assume transition time of 2:00 AM) * day of onset 1:59 AM STD = display name 1:59 AM ST * 2:00 AM STD = display name 3:00 AM DT * day of end 0:59 AM STD = display name 1:59 AM DT * 1:00 AM STD = display name 1:00 AM ST */ public void Test4084933() { // test both SimpleTimeZone and ZoneInfo objects. // @since 1.4 sub4084933(getPST()); sub4084933(TimeZone.getTimeZone("PST")); } private void sub4084933(TimeZone tz) { long offset1 = tz.getOffset(1, 1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (2*60*60*1000)); long offset2 = tz.getOffset(1, 1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (2*60*60*1000)-1); long offset3 = tz.getOffset(1, 1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (1*60*60*1000)); long offset4 = tz.getOffset(1, 1997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (1*60*60*1000)-1); /* * The following was added just for consistency. It shows that going *to* Daylight * Savings Time (PDT) does work at 2am. */ long offset5 = tz.getOffset(1, 1997, Calendar.APRIL, 6, Calendar.SUNDAY, (2*60*60*1000)); long offset6 = tz.getOffset(1, 1997, Calendar.APRIL, 6, Calendar.SUNDAY, (2*60*60*1000)-1); long offset7 = tz.getOffset(1, 1997, Calendar.APRIL, 6, Calendar.SUNDAY, (1*60*60*1000)); long offset8 = tz.getOffset(1, 1997, Calendar.APRIL, 6, Calendar.SUNDAY, (1*60*60*1000)-1); long SToffset = -8 * 60*60*1000L; long DToffset = -7 * 60*60*1000L; if (offset1 != SToffset || offset2 != SToffset || offset3 != SToffset || offset4 != DToffset || offset5 != DToffset || offset6 != SToffset || offset7 != SToffset || offset8 != SToffset) errln("Fail: TimeZone misbehaving"); { } } public void Test4096952() { String[] ZONES = { "GMT", "MET", "IST" }; boolean pass = true; try { for (int i=0; i<ZONES.length; ++i) { TimeZone zone = TimeZone.getTimeZone(ZONES[i]); if (!zone.getID().equals(ZONES[i])) errln("Fail: Test broken; zones not instantiating"); ByteArrayOutputStream baos; ObjectOutputStream ostream = new ObjectOutputStream(baos = new ByteArrayOutputStream()); ostream.writeObject(zone); ostream.close(); baos.close(); ObjectInputStream istream = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray())); TimeZone frankenZone = (TimeZone) istream.readObject(); //logln("Zone: " + zone); //logln("FrankenZone: " + frankenZone); if (!zone.equals(frankenZone)) { logln("TimeZone " + zone.getID() + " not equal to serialized/deserialized one"); pass = false; } } if (!pass) errln("Fail: TimeZone serialization/equality bug"); } catch (IOException e) { errln("Fail: " + e); e.printStackTrace(); } catch (ClassNotFoundException e) { errln("Fail: " + e); e.printStackTrace(); } } public void Test4109314() { Locale locale = Locale.getDefault(); if (!TestUtils.usesGregorianCalendar(locale)) { logln("Skipping this test because locale is " + locale); return; } // test both SimpleTimeZone and ZoneInfo objects. // @since 1.4 sub4109314(getPST()); sub4109314(TimeZone.getTimeZone("PST")); } @SuppressWarnings("deprecation") private void sub4109314(TimeZone PST) { GregorianCalendar testCal = (GregorianCalendar)Calendar.getInstance(); Object[] testData = { PST, new Date(98,Calendar.APRIL,4,22,0), new Date(98, Calendar.APRIL, 5,6,0), PST, new Date(98,Calendar.OCTOBER,24,22,0), new Date(98,Calendar.OCTOBER,25,6,0), }; boolean pass=true; for (int i=0; i<testData.length; i+=3) { testCal.setTimeZone((TimeZone) testData[i]); long t = ((Date)testData[i+1]).getTime(); Date end = (Date) testData[i+2]; while (t < end.getTime()) { testCal.setTime(new Date(t)); if (!checkCalendar314(testCal, (TimeZone) testData[i])) pass = false; t += 60*60*1000L; } } if (!pass) errln("Fail: TZ API inconsistent"); } boolean checkCalendar314(GregorianCalendar testCal, TimeZone testTZ) { // GregorianCalendar testCal = (GregorianCalendar)aCal.clone(); final int ONE_DAY = 24*60*60*1000; int tzOffset, tzRawOffset; Float tzOffsetFloat,tzRawOffsetFloat; // Here is where the user made an error. They were passing in the value of // the MILLSECOND field; you need to pass in the millis in the day in STANDARD // time. int millis = testCal.get(Calendar.MILLISECOND) + 1000 * (testCal.get(Calendar.SECOND) + 60 * (testCal.get(Calendar.MINUTE) + 60 * (testCal.get(Calendar.HOUR_OF_DAY)))) - testCal.get(Calendar.DST_OFFSET); /* Fix up millis to be in range. ASSUME THAT WE ARE NOT AT THE * BEGINNING OR END OF A MONTH. We must add this code because * getOffset() has been changed to be more strict about the parameters * it receives -- it turns out that this test was passing in illegal * values. */ int date = testCal.get(Calendar.DATE); int dow = testCal.get(Calendar.DAY_OF_WEEK); while (millis < 0) { millis += ONE_DAY; --date; dow = Calendar.SUNDAY + ((dow - Calendar.SUNDAY + 6) % 7); } while (millis >= ONE_DAY) { millis -= ONE_DAY; ++date; dow = Calendar.SUNDAY + ((dow - Calendar.SUNDAY + 1) % 7); } tzOffset = testTZ.getOffset(testCal.get(Calendar.ERA), testCal.get(Calendar.YEAR), testCal.get(Calendar.MONTH), date, dow, millis); tzRawOffset = testTZ.getRawOffset(); tzOffsetFloat = new Float((float)tzOffset/(float)3600000); tzRawOffsetFloat = new Float((float)tzRawOffset/(float)3600000); Date testDate = testCal.getTime(); boolean inDaylightTime = testTZ.inDaylightTime(testDate); SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm"); sdf.setCalendar(testCal); String inDaylightTimeString; boolean passed; if (inDaylightTime) { inDaylightTimeString = " DST "; passed = (tzOffset == (tzRawOffset + 3600000)); } else { inDaylightTimeString = " "; passed = (tzOffset == tzRawOffset); } String output = testTZ.getID() + " " + sdf.format(testDate) + " Offset(" + tzOffsetFloat + ")" + " RawOffset(" + tzRawOffsetFloat + ")" + " " + millis/(float)3600000 + " " + inDaylightTimeString; if (passed) output += " "; else output += "ERROR"; if (passed) logln(output); else errln(output); return passed; } /** * CANNOT REPRODUDE * * Yet another _alleged_ bug in TimeZone.getOffset(), a method that never * should have been made public. It's simply too hard to use correctly. * * The original test code failed to do the following: * (1) Call Calendar.setTime() before getting the fields! * (2) Use the right millis (as usual) for getOffset(); they were passing * in the MILLIS field, instead of the STANDARD MILLIS IN DAY. * When you fix these two problems, the test passes, as expected. */ public void Test4126678() { Locale locale = Locale.getDefault(); if (!TestUtils.usesGregorianCalendar(locale)) { logln("Skipping this test because locale is " + locale); return; } // Note: this test depends on the PST time zone. TimeZone initialZone = TimeZone.getDefault(); // test both SimpleTimeZone and ZoneInfo objects. // @since 1.4 sub4126678(getPST()); sub4126678(TimeZone.getTimeZone("PST")); // restore the initial time zone so that this test case // doesn't affect the others. TimeZone.setDefault(initialZone); } @SuppressWarnings("deprecation") private void sub4126678(TimeZone tz) { Calendar cal = Calendar.getInstance(); TimeZone.setDefault(tz); cal.setTimeZone(tz); Date dt = new Date(1998-1900, Calendar.APRIL, 5, 10, 0); // the dt value is local time in PST. if (!tz.inDaylightTime(dt)) errln("We're not in Daylight Savings Time and we should be.\n"); cal.setTime(dt); int era = cal.get(Calendar.ERA); int year = cal.get(Calendar.YEAR); int month = cal.get(Calendar.MONTH); int day = cal.get(Calendar.DATE); int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK); int millis = cal.get(Calendar.MILLISECOND) + (cal.get(Calendar.SECOND) + (cal.get(Calendar.MINUTE) + (cal.get(Calendar.HOUR) * 60) * 60) * 1000) - cal.get(Calendar.DST_OFFSET); long offset = tz.getOffset(era, year, month, day, dayOfWeek, millis); long raw_offset = tz.getRawOffset(); if (offset == raw_offset) { errln("Offsets should not match when in DST"); } } /** * TimeZone.getAvailableIDs(int) throws exception for certain values, * due to a faulty constant in TimeZone.java. */ public void Test4151406() { int max = 0; for (int h=-28; h<=30; ++h) { // h is in half-hours from GMT; rawoffset is in millis int rawoffset = h * 1800000; int hh = (h<0) ? -h : h; String hname = ((h<0) ? "GMT-" : "GMT+") + ((hh/2 < 10) ? "0" : "") + (hh/2) + ':' + ((hh%2==0) ? "00" : "30"); try { String[] ids = TimeZone.getAvailableIDs(rawoffset); if (ids.length > max) max = ids.length; logln(hname + ' ' + ids.length + ((ids.length > 0) ? (" e.g. " + ids[0]) : "")); } catch (Exception e) { errln(hname + ' ' + "Fail: " + e); } } logln("Maximum zones per offset = " + max); } public void Test4151429() { try { TimeZone tz = TimeZone.getTimeZone("GMT"); String name = tz.getDisplayName(true, Integer.MAX_VALUE, Locale.getDefault()); errln("IllegalArgumentException not thrown by TimeZone.getDisplayName()"); } catch(IllegalArgumentException e) {} } /** * SimpleTimeZone accepts illegal DST savings values. These values * must be non-zero. There is no upper limit at this time. */ public void Test4154525() { final int GOOD = 1, BAD = 0; int[] DATA = { 1, GOOD, 0, BAD, -1, BAD, 60*60*1000, GOOD, Integer.MIN_VALUE, BAD, // Integer.MAX_VALUE, ?, // no upper limit on DST savings at this time }; for (int i=0; i<DATA.length; i+=2) { int savings = DATA[i]; boolean valid = DATA[i+1] == GOOD; String method = null; for (int j=0; j<2; ++j) { try { switch (j) { case 0: method = "constructor"; SimpleTimeZone z = new SimpleTimeZone(0, "id", Calendar.JANUARY, 1, 0, 0, Calendar.MARCH, 1, 0, 0, savings); // <- what we're interested in break; case 1: method = "setDSTSavings()"; z = new SimpleTimeZone(0, "GMT"); z.setDSTSavings(savings); break; } if (valid) { logln("Pass: DST savings of " + savings + " accepted by " + method); } else { errln("Fail: DST savings of " + savings + " accepted by " + method); } } catch (IllegalArgumentException e) { if (valid) { errln("Fail: DST savings of " + savings + " to " + method + " gave " + e); } else { logln("Pass: DST savings of " + savings + " to " + method + " gave " + e); } } } } } /** * SimpleTimeZone.hasSameRules() doesn't work for zones with no DST * and different DST parameters. */ public void Test4154537() { // tz1 and tz2 have no DST and different rule parameters SimpleTimeZone tz1 = new SimpleTimeZone(0, "1", 0, 0, 0, 0, 2, 0, 0, 0); SimpleTimeZone tz2 = new SimpleTimeZone(0, "2", 1, 0, 0, 0, 3, 0, 0, 0); // tza and tzA have the same rule params SimpleTimeZone tza = new SimpleTimeZone(0, "a", 0, 1, 0, 0, 3, 2, 0, 0); SimpleTimeZone tzA = new SimpleTimeZone(0, "A", 0, 1, 0, 0, 3, 2, 0, 0); // tzb differs from tza SimpleTimeZone tzb = new SimpleTimeZone(0, "b", 0, 1, 0, 0, 3, 1, 0, 0); if (tz1.useDaylightTime() || tz2.useDaylightTime() || !tza.useDaylightTime() || !tzA.useDaylightTime() || !tzb.useDaylightTime()) { errln("Test is broken -- rewrite it"); } if (!tza.hasSameRules(tzA) || tza.hasSameRules(tzb)) { errln("Fail: hasSameRules() broken for zones with rules"); } if (!tz1.hasSameRules(tz2)) { errln("Fail: hasSameRules() returns false for zones without rules"); errln("zone 1 = " + tz1); errln("zone 2 = " + tz2); } } /** * SimpleTimeZone constructors, setStartRule(), and setEndRule() don't * check for out-of-range arguments. */ public void Test4154542() { final int GOOD = 1; final int BAD = 0; final int GOOD_MONTH = Calendar.JANUARY; final int GOOD_DAY = 1; final int GOOD_DAY_OF_WEEK = Calendar.SUNDAY; final int GOOD_TIME = 0; int[] DATA = { GOOD, Integer.MIN_VALUE, 0, Integer.MAX_VALUE, Integer.MIN_VALUE, GOOD, Calendar.JANUARY, -5, Calendar.SUNDAY, 0, GOOD, Calendar.DECEMBER, 5, Calendar.SATURDAY, 24*60*60*1000-1, GOOD, Calendar.DECEMBER, 5, Calendar.SATURDAY, 24*60*60*1000, BAD, Calendar.DECEMBER, 5, Calendar.SATURDAY, 24*60*60*1000+1, BAD, Calendar.DECEMBER, 5, Calendar.SATURDAY, -1, BAD, Calendar.JANUARY, -6, Calendar.SUNDAY, 0, BAD, Calendar.DECEMBER, 6, Calendar.SATURDAY, 24*60*60*1000, GOOD, Calendar.DECEMBER, 1, 0, 0, GOOD, Calendar.DECEMBER, 31, 0, 0, BAD, Calendar.APRIL, 31, 0, 0, BAD, Calendar.DECEMBER, 32, 0, 0, BAD, Calendar.JANUARY-1, 1, Calendar.SUNDAY, 0, BAD, Calendar.DECEMBER+1, 1, Calendar.SUNDAY, 0, GOOD, Calendar.DECEMBER, 31, -Calendar.SUNDAY, 0, GOOD, Calendar.DECEMBER, 31, -Calendar.SATURDAY, 0, BAD, Calendar.DECEMBER, 32, -Calendar.SATURDAY, 0, BAD, Calendar.DECEMBER, -32, -Calendar.SATURDAY, 0, BAD, Calendar.DECEMBER, 31, -Calendar.SATURDAY-1, 0, }; SimpleTimeZone zone = new SimpleTimeZone(0, "Z"); for (int i=0; i<DATA.length; i+=5) { boolean shouldBeGood = (DATA[i] == GOOD); int month = DATA[i+1]; int day = DATA[i+2]; int dayOfWeek = DATA[i+3]; int time = DATA[i+4]; Exception ex = null; try { zone.setStartRule(month, day, dayOfWeek, time); } catch (IllegalArgumentException e) { ex = e; } if ((ex == null) != shouldBeGood) { errln("setStartRule(month=" + month + ", day=" + day + ", dayOfWeek=" + dayOfWeek + ", time=" + time + (shouldBeGood ? (") should work but throws " + ex) : ") should fail but doesn't")); } ex = null; try { zone.setEndRule(month, day, dayOfWeek, time); } catch (IllegalArgumentException e) { ex = e; } if ((ex == null) != shouldBeGood) { errln("setEndRule(month=" + month + ", day=" + day + ", dayOfWeek=" + dayOfWeek + ", time=" + time + (shouldBeGood ? (") should work but throws " + ex) : ") should fail but doesn't")); } ex = null; try { SimpleTimeZone temp = new SimpleTimeZone(0, "Z", month, day, dayOfWeek, time, GOOD_MONTH, GOOD_DAY, GOOD_DAY_OF_WEEK, GOOD_TIME); } catch (IllegalArgumentException e) { ex = e; } if ((ex == null) != shouldBeGood) { errln("SimpleTimeZone(month=" + month + ", day=" + day + ", dayOfWeek=" + dayOfWeek + ", time=" + time + (shouldBeGood ? (", <end>) should work but throws " + ex) : ", <end>) should fail but doesn't")); } ex = null; try { SimpleTimeZone temp = new SimpleTimeZone(0, "Z", GOOD_MONTH, GOOD_DAY, GOOD_DAY_OF_WEEK, GOOD_TIME, month, day, dayOfWeek, time); } catch (IllegalArgumentException e) { ex = e; } if ((ex == null) != shouldBeGood) { errln("SimpleTimeZone(<start>, month=" + month + ", day=" + day + ", dayOfWeek=" + dayOfWeek + ", time=" + time + (shouldBeGood ? (") should work but throws " + ex) : ") should fail but doesn't")); } } } /** * SimpleTimeZone.getOffset accepts illegal arguments. */ public void Test4154650() { final int GOOD=1, BAD=0; final int GOOD_ERA=GregorianCalendar.AD, GOOD_YEAR=1998, GOOD_MONTH=Calendar.AUGUST; final int GOOD_DAY=2, GOOD_DOW=Calendar.SUNDAY, GOOD_TIME=16*3600000; int[] DATA = { GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, GOOD, GregorianCalendar.BC, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, GOOD, GregorianCalendar.AD, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, BAD, GregorianCalendar.BC-1, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, BAD, GregorianCalendar.AD+1, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME, GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, GOOD_DAY, GOOD_DOW, GOOD_TIME, GOOD, GOOD_ERA, GOOD_YEAR, Calendar.DECEMBER, GOOD_DAY, GOOD_DOW, GOOD_TIME, BAD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY-1, GOOD_DAY, GOOD_DOW, GOOD_TIME, BAD, GOOD_ERA, GOOD_YEAR, Calendar.DECEMBER+1, GOOD_DAY, GOOD_DOW, GOOD_TIME, GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 1, GOOD_DOW, GOOD_TIME, GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 31, GOOD_DOW, GOOD_TIME, BAD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 0, GOOD_DOW, GOOD_TIME, BAD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 32, GOOD_DOW, GOOD_TIME, GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SUNDAY, GOOD_TIME, GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SATURDAY, GOOD_TIME, BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SUNDAY-1, GOOD_TIME, BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SATURDAY+1, GOOD_TIME, GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 0, GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 24*3600000-1, BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, -1, BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 24*3600000, }; TimeZone tz = TimeZone.getDefault(); for (int i=0; i<DATA.length; i+=7) { boolean good = DATA[i] == GOOD; IllegalArgumentException e = null; try { int offset = tz.getOffset(DATA[i+1], DATA[i+2], DATA[i+3], DATA[i+4], DATA[i+5], DATA[i+6]); } catch (IllegalArgumentException ex) { e = ex; } if (good != (e == null)) { errln("Fail: getOffset(" + DATA[i+1] + ", " + DATA[i+2] + ", " + DATA[i+3] + ", " + DATA[i+4] + ", " + DATA[i+5] + ", " + DATA[i+6] + (good ? (") threw " + e) : ") accepts invalid args")); } } } /** * TimeZone constructors allow null IDs. */ public void Test4159922() { TimeZone z = null; // TimeZone API. Only hasSameRules() and setDefault() should // allow null. try { z = TimeZone.getTimeZone((String)null); errln("FAIL: Null allowed in getTimeZone"); } catch (NullPointerException e) {} z = TimeZone.getTimeZone("GMT"); try { z.getDisplayName(false, TimeZone.SHORT, null); errln("FAIL: Null allowed in getDisplayName(3)"); } catch (NullPointerException e) {} try { z.getDisplayName(null); errln("FAIL: Null allowed in getDisplayName(1)"); } catch (NullPointerException e) {} try { if (z.hasSameRules(null)) { errln("FAIL: hasSameRules returned true"); } } catch (NullPointerException e) { errln("FAIL: Null NOT allowed in hasSameRules"); } try { z.inDaylightTime(null); errln("FAIL: Null allowed in inDaylightTime"); } catch (NullPointerException e) {} try { z.setID(null); errln("FAIL: Null allowed in setID"); } catch (NullPointerException e) {} TimeZone save = TimeZone.getDefault(); try { TimeZone.setDefault(null); } catch (NullPointerException e) { errln("FAIL: Null NOT allowed in setDefault"); } finally { TimeZone.setDefault(save); } // SimpleTimeZone API SimpleTimeZone s = null; try { s = new SimpleTimeZone(0, null); errln("FAIL: Null allowed in SimpleTimeZone(2)"); } catch (NullPointerException e) {} try { s = new SimpleTimeZone(0, null, 0, 1, 0, 0, 0, 1, 0, 0); errln("FAIL: Null allowed in SimpleTimeZone(10)"); } catch (NullPointerException e) {} try { s = new SimpleTimeZone(0, null, 0, 1, 0, 0, 0, 1, 0, 0, 1000); errln("FAIL: Null allowed in SimpleTimeZone(11)"); } catch (NullPointerException e) {} } /** * TimeZone broken at midnight. The TimeZone code fails to handle * transitions at midnight correctly. */ @SuppressWarnings("deprecation") public void Test4162593() { SimpleDateFormat fmt = new SimpleDateFormat("z", Locale.US); final int ONE_HOUR = 60*60*1000; TimeZone initialZone = TimeZone.getDefault(); SimpleTimeZone asuncion = new SimpleTimeZone(-4*ONE_HOUR, "America/Asuncion" /*PY%sT*/, Calendar.OCTOBER, 1, 0 /*DOM*/, 0*ONE_HOUR, Calendar.MARCH, 1, 0 /*DOM*/, 0*ONE_HOUR, 1*ONE_HOUR); /* Zone * Starting time * Transition expected between start+1H and start+2H */ Object[] DATA = { new SimpleTimeZone(2*ONE_HOUR, "Asia/Damascus" /*EE%sT*/, Calendar.APRIL, 1, 0 /*DOM*/, 0*ONE_HOUR, Calendar.OCTOBER, 1, 0 /*DOM*/, 0*ONE_HOUR, 1*ONE_HOUR), new int[] {98, Calendar.SEPTEMBER, 30, 22, 0}, Boolean.TRUE, asuncion, new int[] {100, Calendar.FEBRUARY, 28, 22, 0}, Boolean.FALSE, asuncion, new int[] {100, Calendar.FEBRUARY, 29, 22, 0}, Boolean.TRUE, }; String[] zone = new String[4]; try { for (int j=0; j<DATA.length; j+=3) { TimeZone tz = (TimeZone)DATA[j]; TimeZone.setDefault(tz); fmt.setTimeZone(tz); // Must construct the Date object AFTER setting the default zone int[] p = (int[])DATA[j+1]; Date d = new Date(p[0], p[1], p[2], p[3], p[4]); boolean transitionExpected = ((Boolean)DATA[j+2]).booleanValue(); logln(tz.getID() + ":"); for (int i=0; i<4; ++i) { zone[i] = fmt.format(d); logln("" + i + ": " + d); d = new Date(d.getTime() + ONE_HOUR); } if (zone[0].equals(zone[1]) && (zone[1].equals(zone[2]) != transitionExpected) && zone[2].equals(zone[3])) { logln("Ok: transition " + transitionExpected); } else { errln("Fail: boundary transition incorrect"); } } } finally { // restore the initial time zone so that this test case // doesn't affect the others. TimeZone.setDefault(initialZone); } } /** * TimeZone broken in last hour of year */ public void Test4173604() { // test both SimpleTimeZone and ZoneInfo objects. // @since 1.4 sub4173604(getPST()); sub4173604(TimeZone.getTimeZone("PST")); } private void sub4173604(TimeZone pst) { int o22 = pst.getOffset(1, 1998, 11, 31, Calendar.THURSDAY, 22*60*60*1000); int o23 = pst.getOffset(1, 1998, 11, 31, Calendar.THURSDAY, 23*60*60*1000); int o00 = pst.getOffset(1, 1999, 0, 1, Calendar.FRIDAY, 0); if (o22 != o23 || o22 != o00) { errln("Offsets should be the same (for PST), but got: " + "12/31 22:00 " + o22 + ", 12/31 23:00 " + o23 + ", 01/01 00:00 " + o00); } GregorianCalendar cal = new GregorianCalendar(); cal.setTimeZone(pst); cal.clear(); cal.set(1998, Calendar.JANUARY, 1); int lastDST = cal.get(Calendar.DST_OFFSET); int transitions = 0; int delta = 5; while (cal.get(Calendar.YEAR) < 2000) { cal.add(Calendar.MINUTE, delta); if (cal.get(Calendar.DST_OFFSET) != lastDST) { ++transitions; Calendar t = (Calendar)cal.clone(); t.add(Calendar.MINUTE, -delta); logln(t.getTime() + " " + t.get(Calendar.DST_OFFSET)); logln(cal.getTime() + " " + (lastDST=cal.get(Calendar.DST_OFFSET))); } } if (transitions != 4) { errln("Saw " + transitions + " transitions; should have seen 4"); } } /** * getDisplayName doesn't work with unusual savings/offsets. */ @SuppressWarnings("deprecation") public void Test4176686() { // Construct a zone that does not observe DST but // that does have a DST savings (which should be ignored). int offset = 90 * 60000; // 1:30 SimpleTimeZone z1 = new SimpleTimeZone(offset, "_std_zone_"); z1.setDSTSavings(45 * 60000); // 0:45 // Construct a zone that observes DST for the first 6 months. SimpleTimeZone z2 = new SimpleTimeZone(offset, "_dst_zone_"); z2.setDSTSavings(45 * 60000); // 0:45 z2.setStartRule(Calendar.JANUARY, 1, 0); z2.setEndRule(Calendar.JULY, 1, 0); // Also check DateFormat DateFormat fmt1 = new SimpleDateFormat("z"); fmt1.setTimeZone(z1); // Format uses standard zone DateFormat fmt2 = new SimpleDateFormat("z"); fmt2.setTimeZone(z2); // Format uses DST zone Date dst = new Date(1970-1900, Calendar.FEBRUARY, 1); // Time in DST Date std = new Date(1970-1900, Calendar.AUGUST, 1); // Time in standard // Description, Result, Expected Result String[] DATA = { "getDisplayName(false, SHORT)/std zone", z1.getDisplayName(false, TimeZone.SHORT), "GMT+01:30", "getDisplayName(false, LONG)/std zone", z1.getDisplayName(false, TimeZone.LONG ), "GMT+01:30", "getDisplayName(true, SHORT)/std zone", z1.getDisplayName(true, TimeZone.SHORT), "GMT+01:30", "getDisplayName(true, LONG)/std zone", z1.getDisplayName(true, TimeZone.LONG ), "GMT+01:30", "getDisplayName(false, SHORT)/dst zone", z2.getDisplayName(false, TimeZone.SHORT), "GMT+01:30", "getDisplayName(false, LONG)/dst zone", z2.getDisplayName(false, TimeZone.LONG ), "GMT+01:30", "getDisplayName(true, SHORT)/dst zone", z2.getDisplayName(true, TimeZone.SHORT), "GMT+02:15", "getDisplayName(true, LONG)/dst zone", z2.getDisplayName(true, TimeZone.LONG ), "GMT+02:15", "DateFormat.format(std)/std zone", fmt1.format(std), "GMT+01:30", "DateFormat.format(dst)/std zone", fmt1.format(dst), "GMT+01:30", "DateFormat.format(std)/dst zone", fmt2.format(std), "GMT+01:30", "DateFormat.format(dst)/dst zone", fmt2.format(dst), "GMT+02:15", }; for (int i=0; i<DATA.length; i+=3) { if (!DATA[i+1].equals(DATA[i+2])) { errln("FAIL: " + DATA[i] + " -> " + DATA[i+1] + ", exp " + DATA[i+2]); } } } /** * SimpleTimeZone allows invalid DOM values. */ public void Test4184229() { SimpleTimeZone zone = null; try { zone = new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 0); errln("Failed. No exception has been thrown for DOM -1 startDay"); } catch(IllegalArgumentException e) { logln("(a) " + e.getMessage()); } try { zone = new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0); errln("Failed. No exception has been thrown for DOM -1 endDay"); } catch(IllegalArgumentException e) { logln("(b) " + e.getMessage()); } try { zone = new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 0, 1000); errln("Failed. No exception has been thrown for DOM -1 startDay +savings"); } catch(IllegalArgumentException e) { logln("(c) " + e.getMessage()); } try { zone = new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0, 1000); errln("Failed. No exception has been thrown for DOM -1 endDay +savings"); } catch(IllegalArgumentException e) { logln("(d) " + e.getMessage()); } // Make a valid constructor call for subsequent tests. zone = new SimpleTimeZone(0, "A", 0, 1, 0, 0, 0, 1, 0, 0); try { zone.setStartRule(0, -1, 0, 0); errln("Failed. No exception has been thrown for DOM -1 setStartRule +savings"); } catch(IllegalArgumentException e) { logln("(e) " + e.getMessage()); } try { zone.setStartRule(0, -1, 0); errln("Failed. No exception has been thrown for DOM -1 setStartRule"); } catch(IllegalArgumentException e) { logln("(f) " + e.getMessage()); } try { zone.setEndRule(0, -1, 0, 0); errln("Failed. No exception has been thrown for DOM -1 setEndRule +savings"); } catch(IllegalArgumentException e) { logln("(g) " + e.getMessage()); } try { zone.setEndRule(0, -1, 0); errln("Failed. No exception has been thrown for DOM -1 setEndRule"); } catch(IllegalArgumentException e) { logln("(h) " + e.getMessage()); } } /** * SimpleTimeZone.getOffset() throws IllegalArgumentException when to get * of 2/29/1996 (leap day). */ public void Test4208960 () { // test both SimpleTimeZone and ZoneInfo objects. // @since 1.4 sub4208960(getPST()); sub4208960(TimeZone.getTimeZone("PST")); } private void sub4208960(TimeZone tz) { try { int offset = tz.getOffset(GregorianCalendar.AD, 1996, Calendar.FEBRUARY, 29, Calendar.THURSDAY, 0); } catch (IllegalArgumentException e) { errln("FAILED: to get TimeZone.getOffset(2/29/96)"); } try { int offset = tz.getOffset(GregorianCalendar.AD, 1997, Calendar.FEBRUARY, 29, Calendar.THURSDAY, 0); errln("FAILED: TimeZone.getOffset(2/29/97) expected to throw Exception."); } catch (IllegalArgumentException e) { logln("got IllegalArgumentException"); } } /** * 4966229: java.util.Date methods may works incorrect. * sun.util.calendar.ZoneInfo doesn't clone properly. */ @SuppressWarnings("deprecation") public void Test4966229() { TimeZone savedTZ = TimeZone.getDefault(); try { TimeZone.setDefault(TimeZone.getTimeZone("GMT")); Date d = new Date(2100-1900, 5, 1); // specify year >2037 TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles"); Calendar cal = new GregorianCalendar(tz); cal.setTime(d); // Change the raw offset in tz int offset = tz.getRawOffset(); tz.setRawOffset(0); TimeZone tz2 = (TimeZone) tz.clone(); Calendar cal2 = new GregorianCalendar(tz2); cal2.setTime(d); int expectedHourOfDay = cal2.get(cal.HOUR_OF_DAY); // Restore the GMT offset in tz which shouldn't affect tz2 tz.setRawOffset(offset); cal2.setTime(d); int hourOfDay = cal2.get(cal.HOUR_OF_DAY); if (hourOfDay != expectedHourOfDay) { errln("wrong hour of day: got: " + hourOfDay + ", expected: " + expectedHourOfDay); } } finally { TimeZone.setDefault(savedTZ); } } /** * 6433179: (tz) Incorrect DST end for America/Winnipeg and Canada/Central in 2038+ */ public void Test6433179() { // Use the old America/Winnipeg rule for testing. Note that // startMode is WALL_TIME for testing. It's actually // STANDARD_TIME, though. //Rule Winn 1966 2005 - Oct lastSun 2:00s 0 S //Rule Winn 1987 2005 - Apr Sun>=1 2:00s 1:00 D TimeZone tz = new SimpleTimeZone(-6*ONE_HOUR, "America/Winnipeg", Calendar.APRIL, 1, -Calendar.SUNDAY, 2*ONE_HOUR, SimpleTimeZone.WALL_TIME, Calendar.OCTOBER, -1, Calendar.SUNDAY, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME, 1*ONE_HOUR); Calendar cal = Calendar.getInstance(tz, Locale.US); cal.clear(); cal.set(2039, Calendar.OCTOBER, 1); cal.getTime(); cal.set(cal.DAY_OF_WEEK, cal.SUNDAY); cal.set(cal.DAY_OF_WEEK_IN_MONTH, -1); cal.add(Calendar.HOUR_OF_DAY, 2); if (cal.get(cal.DST_OFFSET) == 0) { errln("Should still be in DST."); } } private static final int ONE_HOUR = 60 * 60 * 1000; /** * Returns an instance of SimpleTimeZone for * "PST". (TimeZone.getTimeZone() no longer returns a * SimpleTimeZone object.) * @since 1.4 */ private SimpleTimeZone getPST() { return new SimpleTimeZone(-8*ONE_HOUR, "PST", Calendar.APRIL, 1, -Calendar.SUNDAY, 2*ONE_HOUR, Calendar.OCTOBER, -1, Calendar.SUNDAY, 2*ONE_HOUR, 1*ONE_HOUR); } } //eof