diff options
Diffstat (limited to 'test/java/util/TimeZone/TimeZoneRegression.java')
-rw-r--r-- | test/java/util/TimeZone/TimeZoneRegression.java | 995 |
1 files changed, 995 insertions, 0 deletions
diff --git a/test/java/util/TimeZone/TimeZoneRegression.java b/test/java/util/TimeZone/TimeZoneRegression.java new file mode 100644 index 0000000000..8b9e2f4a22 --- /dev/null +++ b/test/java/util/TimeZone/TimeZoneRegression.java @@ -0,0 +1,995 @@ +/* + * 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 Test4052967() { + logln("*** CHECK TIMEZONE AGAINST HOST OS SETTING ***"); + String id = TimeZone.getDefault().getID(); + logln("user.timezone: " + System.getProperty("user.timezone", "<not set>")); + logln("TimeZone.getDefault().getID(): " + id); + logln(new Date().toString()); + logln("*** THE RESULTS OF THIS TEST MUST BE VERIFIED MANUALLY ***"); + } + + 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() { + // test both SimpleTimeZone and ZoneInfo objects. + // @since 1.4 + if (Locale.getDefault().equals(new Locale("th", "TH"))) { + return; + } + 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() { + // 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 |