Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/java/util/TimeZone/TimeZoneRegression.java
38811 views
/*1* Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 4052967 4073209 4073215 4084933 4096952 4109314 4126678 4151406 415142926* 4154525 4154537 4154542 4154650 4159922 4162593 4173604 4176686 4184229 420896027* 4966229 6433179 6851214 8007520 800857728* @library /java/text/testlib29* @run main/othervm -Djava.locale.providers=JRE,SPI TimeZoneRegression30*/3132import java.util.*;33import java.io.*;34import java.text.*;3536public class TimeZoneRegression extends IntlTest {3738public static void main(String[] args) throws Exception {39new TimeZoneRegression().run(args);40}4142public void Test4052967() {43logln("*** CHECK TIMEZONE AGAINST HOST OS SETTING ***");44String id = TimeZone.getDefault().getID();45logln("user.timezone: " + System.getProperty("user.timezone", "<not set>"));46logln("TimeZone.getDefault().getID(): " + id);47logln(new Date().toString());48logln("*** THE RESULTS OF THIS TEST MUST BE VERIFIED MANUALLY ***");49}5051public void Test4073209() {52TimeZone z1 = TimeZone.getTimeZone("PST");53TimeZone z2 = TimeZone.getTimeZone("PST");54if (z1 == z2) {55errln("Fail: TimeZone should return clones");56}57}5859@SuppressWarnings("deprecation")60public void Test4073215() {61SimpleTimeZone z = new SimpleTimeZone(0, "GMT");62if (z.useDaylightTime()) {63errln("Fail: Fix test to start with non-DST zone");64}65z.setStartRule(Calendar.FEBRUARY, 1, Calendar.SUNDAY, 0);66z.setEndRule(Calendar.MARCH, -1, Calendar.SUNDAY, 0);67if (!z.useDaylightTime()) {68errln("Fail: DST not active");69}70if (z.inDaylightTime(new Date(97, Calendar.JANUARY, 31)) ||71!z.inDaylightTime(new Date(97, Calendar.MARCH, 1)) ||72z.inDaylightTime(new Date(97, Calendar.MARCH, 31))) {73errln("Fail: DST not working as expected");74}75}7677/**78* The expected behavior of TimeZone around the boundaries is:79* (Assume transition time of 2:00 AM)80* day of onset 1:59 AM STD = display name 1:59 AM ST81* 2:00 AM STD = display name 3:00 AM DT82* day of end 0:59 AM STD = display name 1:59 AM DT83* 1:00 AM STD = display name 1:00 AM ST84*/85public void Test4084933() {86// test both SimpleTimeZone and ZoneInfo objects.87// @since 1.488sub4084933(getPST());89sub4084933(TimeZone.getTimeZone("PST"));90}9192private void sub4084933(TimeZone tz) {93long offset1 = tz.getOffset(1,941997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (2*60*60*1000));95long offset2 = tz.getOffset(1,961997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (2*60*60*1000)-1);9798long offset3 = tz.getOffset(1,991997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (1*60*60*1000));100long offset4 = tz.getOffset(1,1011997, Calendar.OCTOBER, 26, Calendar.SUNDAY, (1*60*60*1000)-1);102103/*104* The following was added just for consistency. It shows that going *to* Daylight105* Savings Time (PDT) does work at 2am.106*/107108long offset5 = tz.getOffset(1,1091997, Calendar.APRIL, 6, Calendar.SUNDAY, (2*60*60*1000));110long offset6 = tz.getOffset(1,1111997, Calendar.APRIL, 6, Calendar.SUNDAY, (2*60*60*1000)-1);112113long offset7 = tz.getOffset(1,1141997, Calendar.APRIL, 6, Calendar.SUNDAY, (1*60*60*1000));115long offset8 = tz.getOffset(1,1161997, Calendar.APRIL, 6, Calendar.SUNDAY, (1*60*60*1000)-1);117118long SToffset = -8 * 60*60*1000L;119long DToffset = -7 * 60*60*1000L;120if (offset1 != SToffset || offset2 != SToffset ||121offset3 != SToffset || offset4 != DToffset ||122offset5 != DToffset || offset6 != SToffset ||123offset7 != SToffset || offset8 != SToffset)124errln("Fail: TimeZone misbehaving"); {125}126}127128public void Test4096952() {129String[] ZONES = { "GMT", "MET", "IST" };130boolean pass = true;131try {132for (int i=0; i<ZONES.length; ++i) {133TimeZone zone = TimeZone.getTimeZone(ZONES[i]);134if (!zone.getID().equals(ZONES[i]))135errln("Fail: Test broken; zones not instantiating");136137ByteArrayOutputStream baos;138ObjectOutputStream ostream =139new ObjectOutputStream(baos = new140ByteArrayOutputStream());141ostream.writeObject(zone);142ostream.close();143baos.close();144ObjectInputStream istream =145new ObjectInputStream(new146ByteArrayInputStream(baos.toByteArray()));147TimeZone frankenZone = (TimeZone) istream.readObject();148//logln("Zone: " + zone);149//logln("FrankenZone: " + frankenZone);150if (!zone.equals(frankenZone)) {151logln("TimeZone " + zone.getID() +152" not equal to serialized/deserialized one");153pass = false;154}155}156if (!pass) errln("Fail: TimeZone serialization/equality bug");157}158catch (IOException e) {159errln("Fail: " + e);160e.printStackTrace();161}162catch (ClassNotFoundException e) {163errln("Fail: " + e);164e.printStackTrace();165}166}167168public void Test4109314() {169// test both SimpleTimeZone and ZoneInfo objects.170// @since 1.4171if (Locale.getDefault().equals(new Locale("th", "TH"))) {172return;173}174sub4109314(getPST());175sub4109314(TimeZone.getTimeZone("PST"));176}177178179@SuppressWarnings("deprecation")180private void sub4109314(TimeZone PST) {181GregorianCalendar testCal = (GregorianCalendar)Calendar.getInstance();182Object[] testData = {183PST, new Date(98,Calendar.APRIL,4,22,0), new Date(98, Calendar.APRIL, 5,6,0),184PST, new Date(98,Calendar.OCTOBER,24,22,0), new Date(98,Calendar.OCTOBER,25,6,0),185};186boolean pass=true;187for (int i=0; i<testData.length; i+=3) {188testCal.setTimeZone((TimeZone) testData[i]);189long t = ((Date)testData[i+1]).getTime();190Date end = (Date) testData[i+2];191while (t < end.getTime()) {192testCal.setTime(new Date(t));193if (!checkCalendar314(testCal, (TimeZone) testData[i]))194pass = false;195t += 60*60*1000L;196}197}198if (!pass) errln("Fail: TZ API inconsistent");199}200201boolean checkCalendar314(GregorianCalendar testCal, TimeZone testTZ) {202// GregorianCalendar testCal = (GregorianCalendar)aCal.clone();203204final int ONE_DAY = 24*60*60*1000;205206int tzOffset, tzRawOffset;207Float tzOffsetFloat,tzRawOffsetFloat;208// Here is where the user made an error. They were passing in the value of209// the MILLSECOND field; you need to pass in the millis in the day in STANDARD210// time.211int millis = testCal.get(Calendar.MILLISECOND) +2121000 * (testCal.get(Calendar.SECOND) +21360 * (testCal.get(Calendar.MINUTE) +21460 * (testCal.get(Calendar.HOUR_OF_DAY)))) -215testCal.get(Calendar.DST_OFFSET);216217/* Fix up millis to be in range. ASSUME THAT WE ARE NOT AT THE218* BEGINNING OR END OF A MONTH. We must add this code because219* getOffset() has been changed to be more strict about the parameters220* it receives -- it turns out that this test was passing in illegal221* values. */222int date = testCal.get(Calendar.DATE);223int dow = testCal.get(Calendar.DAY_OF_WEEK);224while (millis < 0) {225millis += ONE_DAY;226--date;227dow = Calendar.SUNDAY + ((dow - Calendar.SUNDAY + 6) % 7);228}229while (millis >= ONE_DAY) {230millis -= ONE_DAY;231++date;232dow = Calendar.SUNDAY + ((dow - Calendar.SUNDAY + 1) % 7);233}234235tzOffset = testTZ.getOffset(testCal.get(Calendar.ERA),236testCal.get(Calendar.YEAR),237testCal.get(Calendar.MONTH),238date,239dow,240millis);241tzRawOffset = testTZ.getRawOffset();242tzOffsetFloat = new Float((float)tzOffset/(float)3600000);243tzRawOffsetFloat = new Float((float)tzRawOffset/(float)3600000);244245Date testDate = testCal.getTime();246247boolean inDaylightTime = testTZ.inDaylightTime(testDate);248SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm");249sdf.setCalendar(testCal);250String inDaylightTimeString;251252boolean passed;253254if (inDaylightTime)255{256inDaylightTimeString = " DST ";257passed = (tzOffset == (tzRawOffset + 3600000));258}259else260{261inDaylightTimeString = " ";262passed = (tzOffset == tzRawOffset);263}264265String output = testTZ.getID() + " " + sdf.format(testDate) +266" Offset(" + tzOffsetFloat + ")" +267" RawOffset(" + tzRawOffsetFloat + ")" +268" " + millis/(float)3600000 + " " +269inDaylightTimeString;270271if (passed)272output += " ";273else274output += "ERROR";275276if (passed) logln(output); else errln(output);277return passed;278}279280/**281* CANNOT REPRODUDE282*283* Yet another _alleged_ bug in TimeZone.getOffset(), a method that never284* should have been made public. It's simply too hard to use correctly.285*286* The original test code failed to do the following:287* (1) Call Calendar.setTime() before getting the fields!288* (2) Use the right millis (as usual) for getOffset(); they were passing289* in the MILLIS field, instead of the STANDARD MILLIS IN DAY.290* When you fix these two problems, the test passes, as expected.291*/292public void Test4126678() {293// Note: this test depends on the PST time zone.294TimeZone initialZone = TimeZone.getDefault();295296// test both SimpleTimeZone and ZoneInfo objects.297// @since 1.4298sub4126678(getPST());299sub4126678(TimeZone.getTimeZone("PST"));300301// restore the initial time zone so that this test case302// doesn't affect the others.303TimeZone.setDefault(initialZone);304}305306@SuppressWarnings("deprecation")307private void sub4126678(TimeZone tz) {308Calendar cal = Calendar.getInstance();309TimeZone.setDefault(tz);310cal.setTimeZone(tz);311312Date dt = new Date(1998-1900, Calendar.APRIL, 5, 10, 0);313// the dt value is local time in PST.314if (!tz.inDaylightTime(dt))315errln("We're not in Daylight Savings Time and we should be.\n");316317cal.setTime(dt);318int era = cal.get(Calendar.ERA);319int year = cal.get(Calendar.YEAR);320int month = cal.get(Calendar.MONTH);321int day = cal.get(Calendar.DATE);322int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);323int millis = cal.get(Calendar.MILLISECOND) +324(cal.get(Calendar.SECOND) +325(cal.get(Calendar.MINUTE) +326(cal.get(Calendar.HOUR) * 60) * 60) * 1000) -327cal.get(Calendar.DST_OFFSET);328329long offset = tz.getOffset(era, year, month, day, dayOfWeek, millis);330long raw_offset = tz.getRawOffset();331if (offset == raw_offset) {332errln("Offsets should not match when in DST");333}334}335336/**337* TimeZone.getAvailableIDs(int) throws exception for certain values,338* due to a faulty constant in TimeZone.java.339*/340public void Test4151406() {341int max = 0;342for (int h=-28; h<=30; ++h) {343// h is in half-hours from GMT; rawoffset is in millis344int rawoffset = h * 1800000;345int hh = (h<0) ? -h : h;346String hname = ((h<0) ? "GMT-" : "GMT+") +347((hh/2 < 10) ? "0" : "") +348(hh/2) + ':' +349((hh%2==0) ? "00" : "30");350try {351String[] ids = TimeZone.getAvailableIDs(rawoffset);352if (ids.length > max) max = ids.length;353logln(hname + ' ' + ids.length +354((ids.length > 0) ? (" e.g. " + ids[0]) : ""));355} catch (Exception e) {356errln(hname + ' ' + "Fail: " + e);357}358}359logln("Maximum zones per offset = " + max);360}361362public void Test4151429() {363try {364TimeZone tz = TimeZone.getTimeZone("GMT");365String name = tz.getDisplayName(true, Integer.MAX_VALUE,366Locale.getDefault());367errln("IllegalArgumentException not thrown by TimeZone.getDisplayName()");368} catch(IllegalArgumentException e) {}369}370371/**372* SimpleTimeZone accepts illegal DST savings values. These values373* must be non-zero. There is no upper limit at this time.374*/375public void Test4154525() {376final int GOOD = 1, BAD = 0;377int[] DATA = {3781, GOOD,3790, BAD,380-1, BAD,38160*60*1000, GOOD,382Integer.MIN_VALUE, BAD,383// Integer.MAX_VALUE, ?, // no upper limit on DST savings at this time384};385for (int i=0; i<DATA.length; i+=2) {386int savings = DATA[i];387boolean valid = DATA[i+1] == GOOD;388String method = null;389for (int j=0; j<2; ++j) {390try {391switch (j) {392case 0:393method = "constructor";394SimpleTimeZone z = new SimpleTimeZone(0, "id",395Calendar.JANUARY, 1, 0, 0,396Calendar.MARCH, 1, 0, 0,397savings); // <- what we're interested in398break;399case 1:400method = "setDSTSavings()";401z = new SimpleTimeZone(0, "GMT");402z.setDSTSavings(savings);403break;404}405if (valid) {406logln("Pass: DST savings of " + savings + " accepted by " + method);407} else {408errln("Fail: DST savings of " + savings + " accepted by " + method);409}410} catch (IllegalArgumentException e) {411if (valid) {412errln("Fail: DST savings of " + savings + " to " + method + " gave " + e);413} else {414logln("Pass: DST savings of " + savings + " to " + method + " gave " + e);415}416}417}418}419}420421/**422* SimpleTimeZone.hasSameRules() doesn't work for zones with no DST423* and different DST parameters.424*/425public void Test4154537() {426// tz1 and tz2 have no DST and different rule parameters427SimpleTimeZone tz1 = new SimpleTimeZone(0, "1", 0, 0, 0, 0, 2, 0, 0, 0);428SimpleTimeZone tz2 = new SimpleTimeZone(0, "2", 1, 0, 0, 0, 3, 0, 0, 0);429// tza and tzA have the same rule params430SimpleTimeZone tza = new SimpleTimeZone(0, "a", 0, 1, 0, 0, 3, 2, 0, 0);431SimpleTimeZone tzA = new SimpleTimeZone(0, "A", 0, 1, 0, 0, 3, 2, 0, 0);432// tzb differs from tza433SimpleTimeZone tzb = new SimpleTimeZone(0, "b", 0, 1, 0, 0, 3, 1, 0, 0);434if (tz1.useDaylightTime() || tz2.useDaylightTime() ||435!tza.useDaylightTime() || !tzA.useDaylightTime() ||436!tzb.useDaylightTime()) {437errln("Test is broken -- rewrite it");438}439if (!tza.hasSameRules(tzA) || tza.hasSameRules(tzb)) {440errln("Fail: hasSameRules() broken for zones with rules");441}442if (!tz1.hasSameRules(tz2)) {443errln("Fail: hasSameRules() returns false for zones without rules");444errln("zone 1 = " + tz1);445errln("zone 2 = " + tz2);446}447}448449/**450* SimpleTimeZone constructors, setStartRule(), and setEndRule() don't451* check for out-of-range arguments.452*/453public void Test4154542() {454final int GOOD = 1;455final int BAD = 0;456457final int GOOD_MONTH = Calendar.JANUARY;458final int GOOD_DAY = 1;459final int GOOD_DAY_OF_WEEK = Calendar.SUNDAY;460final int GOOD_TIME = 0;461462int[] DATA = {463GOOD, Integer.MIN_VALUE, 0, Integer.MAX_VALUE, Integer.MIN_VALUE,464GOOD, Calendar.JANUARY, -5, Calendar.SUNDAY, 0,465GOOD, Calendar.DECEMBER, 5, Calendar.SATURDAY, 24*60*60*1000-1,466GOOD, Calendar.DECEMBER, 5, Calendar.SATURDAY, 24*60*60*1000,467BAD, Calendar.DECEMBER, 5, Calendar.SATURDAY, 24*60*60*1000+1,468BAD, Calendar.DECEMBER, 5, Calendar.SATURDAY, -1,469BAD, Calendar.JANUARY, -6, Calendar.SUNDAY, 0,470BAD, Calendar.DECEMBER, 6, Calendar.SATURDAY, 24*60*60*1000,471GOOD, Calendar.DECEMBER, 1, 0, 0,472GOOD, Calendar.DECEMBER, 31, 0, 0,473BAD, Calendar.APRIL, 31, 0, 0,474BAD, Calendar.DECEMBER, 32, 0, 0,475BAD, Calendar.JANUARY-1, 1, Calendar.SUNDAY, 0,476BAD, Calendar.DECEMBER+1, 1, Calendar.SUNDAY, 0,477GOOD, Calendar.DECEMBER, 31, -Calendar.SUNDAY, 0,478GOOD, Calendar.DECEMBER, 31, -Calendar.SATURDAY, 0,479BAD, Calendar.DECEMBER, 32, -Calendar.SATURDAY, 0,480BAD, Calendar.DECEMBER, -32, -Calendar.SATURDAY, 0,481BAD, Calendar.DECEMBER, 31, -Calendar.SATURDAY-1, 0,482};483SimpleTimeZone zone = new SimpleTimeZone(0, "Z");484for (int i=0; i<DATA.length; i+=5) {485boolean shouldBeGood = (DATA[i] == GOOD);486int month = DATA[i+1];487int day = DATA[i+2];488int dayOfWeek = DATA[i+3];489int time = DATA[i+4];490491Exception ex = null;492try {493zone.setStartRule(month, day, dayOfWeek, time);494} catch (IllegalArgumentException e) {495ex = e;496}497if ((ex == null) != shouldBeGood) {498errln("setStartRule(month=" + month + ", day=" + day +499", dayOfWeek=" + dayOfWeek + ", time=" + time +500(shouldBeGood ? (") should work but throws " + ex)501: ") should fail but doesn't"));502}503504ex = null;505try {506zone.setEndRule(month, day, dayOfWeek, time);507} catch (IllegalArgumentException e) {508ex = e;509}510if ((ex == null) != shouldBeGood) {511errln("setEndRule(month=" + month + ", day=" + day +512", dayOfWeek=" + dayOfWeek + ", time=" + time +513(shouldBeGood ? (") should work but throws " + ex)514: ") should fail but doesn't"));515}516517ex = null;518try {519SimpleTimeZone temp = new SimpleTimeZone(0, "Z",520month, day, dayOfWeek, time,521GOOD_MONTH, GOOD_DAY, GOOD_DAY_OF_WEEK, GOOD_TIME);522} catch (IllegalArgumentException e) {523ex = e;524}525if ((ex == null) != shouldBeGood) {526errln("SimpleTimeZone(month=" + month + ", day=" + day +527", dayOfWeek=" + dayOfWeek + ", time=" + time +528(shouldBeGood ? (", <end>) should work but throws " + ex)529: ", <end>) should fail but doesn't"));530}531532ex = null;533try {534SimpleTimeZone temp = new SimpleTimeZone(0, "Z",535GOOD_MONTH, GOOD_DAY, GOOD_DAY_OF_WEEK, GOOD_TIME,536month, day, dayOfWeek, time);537} catch (IllegalArgumentException e) {538ex = e;539}540if ((ex == null) != shouldBeGood) {541errln("SimpleTimeZone(<start>, month=" + month + ", day=" + day +542", dayOfWeek=" + dayOfWeek + ", time=" + time +543(shouldBeGood ? (") should work but throws " + ex)544: ") should fail but doesn't"));545}546}547}548549/**550* SimpleTimeZone.getOffset accepts illegal arguments.551*/552public void Test4154650() {553final int GOOD=1, BAD=0;554final int GOOD_ERA=GregorianCalendar.AD, GOOD_YEAR=1998, GOOD_MONTH=Calendar.AUGUST;555final int GOOD_DAY=2, GOOD_DOW=Calendar.SUNDAY, GOOD_TIME=16*3600000;556int[] DATA = {557GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,558559GOOD, GregorianCalendar.BC, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,560GOOD, GregorianCalendar.AD, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,561BAD, GregorianCalendar.BC-1, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,562BAD, GregorianCalendar.AD+1, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, GOOD_TIME,563564GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, GOOD_DAY, GOOD_DOW, GOOD_TIME,565GOOD, GOOD_ERA, GOOD_YEAR, Calendar.DECEMBER, GOOD_DAY, GOOD_DOW, GOOD_TIME,566BAD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY-1, GOOD_DAY, GOOD_DOW, GOOD_TIME,567BAD, GOOD_ERA, GOOD_YEAR, Calendar.DECEMBER+1, GOOD_DAY, GOOD_DOW, GOOD_TIME,568569GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 1, GOOD_DOW, GOOD_TIME,570GOOD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 31, GOOD_DOW, GOOD_TIME,571BAD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 0, GOOD_DOW, GOOD_TIME,572BAD, GOOD_ERA, GOOD_YEAR, Calendar.JANUARY, 32, GOOD_DOW, GOOD_TIME,573574GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SUNDAY, GOOD_TIME,575GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SATURDAY, GOOD_TIME,576BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SUNDAY-1, GOOD_TIME,577BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, Calendar.SATURDAY+1, GOOD_TIME,578579GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 0,580GOOD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 24*3600000-1,581BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, -1,582BAD, GOOD_ERA, GOOD_YEAR, GOOD_MONTH, GOOD_DAY, GOOD_DOW, 24*3600000,583};584585TimeZone tz = TimeZone.getDefault();586for (int i=0; i<DATA.length; i+=7) {587boolean good = DATA[i] == GOOD;588IllegalArgumentException e = null;589try {590int offset = tz.getOffset(DATA[i+1], DATA[i+2], DATA[i+3],591DATA[i+4], DATA[i+5], DATA[i+6]);592} catch (IllegalArgumentException ex) {593e = ex;594}595if (good != (e == null)) {596errln("Fail: getOffset(" +597DATA[i+1] + ", " + DATA[i+2] + ", " + DATA[i+3] + ", " +598DATA[i+4] + ", " + DATA[i+5] + ", " + DATA[i+6] +599(good ? (") threw " + e) : ") accepts invalid args"));600}601}602}603604/**605* TimeZone constructors allow null IDs.606*/607public void Test4159922() {608TimeZone z = null;609610// TimeZone API. Only hasSameRules() and setDefault() should611// allow null.612try {613z = TimeZone.getTimeZone((String)null);614errln("FAIL: Null allowed in getTimeZone");615} catch (NullPointerException e) {}616z = TimeZone.getTimeZone("GMT");617try {618z.getDisplayName(false, TimeZone.SHORT, null);619errln("FAIL: Null allowed in getDisplayName(3)");620} catch (NullPointerException e) {}621try {622z.getDisplayName(null);623errln("FAIL: Null allowed in getDisplayName(1)");624} catch (NullPointerException e) {}625try {626if (z.hasSameRules(null)) {627errln("FAIL: hasSameRules returned true");628}629} catch (NullPointerException e) {630errln("FAIL: Null NOT allowed in hasSameRules");631}632try {633z.inDaylightTime(null);634errln("FAIL: Null allowed in inDaylightTime");635} catch (NullPointerException e) {}636try {637z.setID(null);638errln("FAIL: Null allowed in setID");639} catch (NullPointerException e) {}640641TimeZone save = TimeZone.getDefault();642try {643TimeZone.setDefault(null);644} catch (NullPointerException e) {645errln("FAIL: Null NOT allowed in setDefault");646} finally {647TimeZone.setDefault(save);648}649650// SimpleTimeZone API651SimpleTimeZone s = null;652try {653s = new SimpleTimeZone(0, null);654errln("FAIL: Null allowed in SimpleTimeZone(2)");655} catch (NullPointerException e) {}656try {657s = new SimpleTimeZone(0, null, 0, 1, 0, 0, 0, 1, 0, 0);658errln("FAIL: Null allowed in SimpleTimeZone(10)");659} catch (NullPointerException e) {}660try {661s = new SimpleTimeZone(0, null, 0, 1, 0, 0, 0, 1, 0, 0, 1000);662errln("FAIL: Null allowed in SimpleTimeZone(11)");663} catch (NullPointerException e) {}664}665666/**667* TimeZone broken at midnight. The TimeZone code fails to handle668* transitions at midnight correctly.669*/670@SuppressWarnings("deprecation")671public void Test4162593() {672SimpleDateFormat fmt = new SimpleDateFormat("z", Locale.US);673final int ONE_HOUR = 60*60*1000;674TimeZone initialZone = TimeZone.getDefault();675676SimpleTimeZone asuncion = new SimpleTimeZone(-4*ONE_HOUR, "America/Asuncion" /*PY%sT*/,677Calendar.OCTOBER, 1, 0 /*DOM*/, 0*ONE_HOUR,678Calendar.MARCH, 1, 0 /*DOM*/, 0*ONE_HOUR, 1*ONE_HOUR);679680/* Zone681* Starting time682* Transition expected between start+1H and start+2H683*/684Object[] DATA = {685new SimpleTimeZone(2*ONE_HOUR, "Asia/Damascus" /*EE%sT*/,686Calendar.APRIL, 1, 0 /*DOM*/, 0*ONE_HOUR,687Calendar.OCTOBER, 1, 0 /*DOM*/, 0*ONE_HOUR, 1*ONE_HOUR),688new int[] {98, Calendar.SEPTEMBER, 30, 22, 0},689Boolean.TRUE,690691asuncion,692new int[] {100, Calendar.FEBRUARY, 28, 22, 0},693Boolean.FALSE,694695asuncion,696new int[] {100, Calendar.FEBRUARY, 29, 22, 0},697Boolean.TRUE,698};699700String[] zone = new String[4];701702try {703for (int j=0; j<DATA.length; j+=3) {704TimeZone tz = (TimeZone)DATA[j];705TimeZone.setDefault(tz);706fmt.setTimeZone(tz);707708// Must construct the Date object AFTER setting the default zone709int[] p = (int[])DATA[j+1];710Date d = new Date(p[0], p[1], p[2], p[3], p[4]);711boolean transitionExpected = ((Boolean)DATA[j+2]).booleanValue();712713logln(tz.getID() + ":");714for (int i=0; i<4; ++i) {715zone[i] = fmt.format(d);716logln("" + i + ": " + d);717d = new Date(d.getTime() + ONE_HOUR);718}719if (zone[0].equals(zone[1]) &&720(zone[1].equals(zone[2]) != transitionExpected) &&721zone[2].equals(zone[3])) {722logln("Ok: transition " + transitionExpected);723} else {724errln("Fail: boundary transition incorrect");725}726}727}728finally {729// restore the initial time zone so that this test case730// doesn't affect the others.731TimeZone.setDefault(initialZone);732}733}734735/**736* TimeZone broken in last hour of year737*/738public void Test4173604() {739// test both SimpleTimeZone and ZoneInfo objects.740// @since 1.4741sub4173604(getPST());742sub4173604(TimeZone.getTimeZone("PST"));743}744745private void sub4173604(TimeZone pst) {746int o22 = pst.getOffset(1, 1998, 11, 31, Calendar.THURSDAY, 22*60*60*1000);747int o23 = pst.getOffset(1, 1998, 11, 31, Calendar.THURSDAY, 23*60*60*1000);748int o00 = pst.getOffset(1, 1999, 0, 1, Calendar.FRIDAY, 0);749if (o22 != o23 || o22 != o00) {750errln("Offsets should be the same (for PST), but got: " +751"12/31 22:00 " + o22 +752", 12/31 23:00 " + o23 +753", 01/01 00:00 " + o00);754}755756GregorianCalendar cal = new GregorianCalendar();757cal.setTimeZone(pst);758cal.clear();759cal.set(1998, Calendar.JANUARY, 1);760int lastDST = cal.get(Calendar.DST_OFFSET);761int transitions = 0;762int delta = 5;763while (cal.get(Calendar.YEAR) < 2000) {764cal.add(Calendar.MINUTE, delta);765if (cal.get(Calendar.DST_OFFSET) != lastDST) {766++transitions;767Calendar t = (Calendar)cal.clone();768t.add(Calendar.MINUTE, -delta);769logln(t.getTime() + " " + t.get(Calendar.DST_OFFSET));770logln(cal.getTime() + " " + (lastDST=cal.get(Calendar.DST_OFFSET)));771}772}773if (transitions != 4) {774errln("Saw " + transitions + " transitions; should have seen 4");775}776}777778/**779* getDisplayName doesn't work with unusual savings/offsets.780*/781@SuppressWarnings("deprecation")782public void Test4176686() {783// Construct a zone that does not observe DST but784// that does have a DST savings (which should be ignored).785int offset = 90 * 60000; // 1:30786SimpleTimeZone z1 = new SimpleTimeZone(offset, "_std_zone_");787z1.setDSTSavings(45 * 60000); // 0:45788789// Construct a zone that observes DST for the first 6 months.790SimpleTimeZone z2 = new SimpleTimeZone(offset, "_dst_zone_");791z2.setDSTSavings(45 * 60000); // 0:45792z2.setStartRule(Calendar.JANUARY, 1, 0);793z2.setEndRule(Calendar.JULY, 1, 0);794795// Also check DateFormat796DateFormat fmt1 = new SimpleDateFormat("z");797fmt1.setTimeZone(z1); // Format uses standard zone798DateFormat fmt2 = new SimpleDateFormat("z");799fmt2.setTimeZone(z2); // Format uses DST zone800Date dst = new Date(1970-1900, Calendar.FEBRUARY, 1); // Time in DST801Date std = new Date(1970-1900, Calendar.AUGUST, 1); // Time in standard802803// Description, Result, Expected Result804String[] DATA = {805"getDisplayName(false, SHORT)/std zone",806z1.getDisplayName(false, TimeZone.SHORT), "GMT+01:30",807"getDisplayName(false, LONG)/std zone",808z1.getDisplayName(false, TimeZone.LONG ), "GMT+01:30",809"getDisplayName(true, SHORT)/std zone",810z1.getDisplayName(true, TimeZone.SHORT), "GMT+01:30",811"getDisplayName(true, LONG)/std zone",812z1.getDisplayName(true, TimeZone.LONG ), "GMT+01:30",813"getDisplayName(false, SHORT)/dst zone",814z2.getDisplayName(false, TimeZone.SHORT), "GMT+01:30",815"getDisplayName(false, LONG)/dst zone",816z2.getDisplayName(false, TimeZone.LONG ), "GMT+01:30",817"getDisplayName(true, SHORT)/dst zone",818z2.getDisplayName(true, TimeZone.SHORT), "GMT+02:15",819"getDisplayName(true, LONG)/dst zone",820z2.getDisplayName(true, TimeZone.LONG ), "GMT+02:15",821"DateFormat.format(std)/std zone", fmt1.format(std), "GMT+01:30",822"DateFormat.format(dst)/std zone", fmt1.format(dst), "GMT+01:30",823"DateFormat.format(std)/dst zone", fmt2.format(std), "GMT+01:30",824"DateFormat.format(dst)/dst zone", fmt2.format(dst), "GMT+02:15",825};826827for (int i=0; i<DATA.length; i+=3) {828if (!DATA[i+1].equals(DATA[i+2])) {829errln("FAIL: " + DATA[i] + " -> " + DATA[i+1] + ", exp " + DATA[i+2]);830}831}832}833834/**835* SimpleTimeZone allows invalid DOM values.836*/837public void Test4184229() {838SimpleTimeZone zone = null;839try {840zone = new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 0);841errln("Failed. No exception has been thrown for DOM -1 startDay");842} catch(IllegalArgumentException e) {843logln("(a) " + e.getMessage());844}845try {846zone = new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0);847errln("Failed. No exception has been thrown for DOM -1 endDay");848} catch(IllegalArgumentException e) {849logln("(b) " + e.getMessage());850}851try {852zone = new SimpleTimeZone(0, "A", 0, -1, 0, 0, 0, 0, 0, 0, 1000);853errln("Failed. No exception has been thrown for DOM -1 startDay +savings");854} catch(IllegalArgumentException e) {855logln("(c) " + e.getMessage());856}857try {858zone = new SimpleTimeZone(0, "A", 0, 0, 0, 0, 0, -1, 0, 0, 1000);859errln("Failed. No exception has been thrown for DOM -1 endDay +savings");860} catch(IllegalArgumentException e) {861logln("(d) " + e.getMessage());862}863// Make a valid constructor call for subsequent tests.864zone = new SimpleTimeZone(0, "A", 0, 1, 0, 0, 0, 1, 0, 0);865try {866zone.setStartRule(0, -1, 0, 0);867errln("Failed. No exception has been thrown for DOM -1 setStartRule +savings");868} catch(IllegalArgumentException e) {869logln("(e) " + e.getMessage());870}871try {872zone.setStartRule(0, -1, 0);873errln("Failed. No exception has been thrown for DOM -1 setStartRule");874} catch(IllegalArgumentException e) {875logln("(f) " + e.getMessage());876}877try {878zone.setEndRule(0, -1, 0, 0);879errln("Failed. No exception has been thrown for DOM -1 setEndRule +savings");880} catch(IllegalArgumentException e) {881logln("(g) " + e.getMessage());882}883try {884zone.setEndRule(0, -1, 0);885errln("Failed. No exception has been thrown for DOM -1 setEndRule");886} catch(IllegalArgumentException e) {887logln("(h) " + e.getMessage());888}889}890891/**892* SimpleTimeZone.getOffset() throws IllegalArgumentException when to get893* of 2/29/1996 (leap day).894*/895public void Test4208960 () {896// test both SimpleTimeZone and ZoneInfo objects.897// @since 1.4898sub4208960(getPST());899sub4208960(TimeZone.getTimeZone("PST"));900}901902private void sub4208960(TimeZone tz) {903try {904int offset = tz.getOffset(GregorianCalendar.AD, 1996, Calendar.FEBRUARY, 29,905Calendar.THURSDAY, 0);906} catch (IllegalArgumentException e) {907errln("FAILED: to get TimeZone.getOffset(2/29/96)");908}909try {910int offset = tz.getOffset(GregorianCalendar.AD, 1997, Calendar.FEBRUARY, 29,911Calendar.THURSDAY, 0);912errln("FAILED: TimeZone.getOffset(2/29/97) expected to throw Exception.");913} catch (IllegalArgumentException e) {914logln("got IllegalArgumentException");915}916}917918/**919* 4966229: java.util.Date methods may works incorrect.920* sun.util.calendar.ZoneInfo doesn't clone properly.921*/922@SuppressWarnings("deprecation")923public void Test4966229() {924TimeZone savedTZ = TimeZone.getDefault();925try {926TimeZone.setDefault(TimeZone.getTimeZone("GMT"));927Date d = new Date(2100-1900, 5, 1); // specify year >2037928TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");929930Calendar cal = new GregorianCalendar(tz);931cal.setTime(d);932933// Change the raw offset in tz934int offset = tz.getRawOffset();935tz.setRawOffset(0);936937TimeZone tz2 = (TimeZone) tz.clone();938Calendar cal2 = new GregorianCalendar(tz2);939cal2.setTime(d);940int expectedHourOfDay = cal2.get(cal.HOUR_OF_DAY);941942// Restore the GMT offset in tz which shouldn't affect tz2943tz.setRawOffset(offset);944cal2.setTime(d);945int hourOfDay = cal2.get(cal.HOUR_OF_DAY);946if (hourOfDay != expectedHourOfDay) {947errln("wrong hour of day: got: " + hourOfDay948+ ", expected: " + expectedHourOfDay);949}950} finally {951TimeZone.setDefault(savedTZ);952}953}954955/**956* 6433179: (tz) Incorrect DST end for America/Winnipeg and Canada/Central in 2038+957*/958public void Test6433179() {959// Use the old America/Winnipeg rule for testing. Note that960// startMode is WALL_TIME for testing. It's actually961// STANDARD_TIME, though.962//Rule Winn 1966 2005 - Oct lastSun 2:00s 0 S963//Rule Winn 1987 2005 - Apr Sun>=1 2:00s 1:00 D964TimeZone tz = new SimpleTimeZone(-6*ONE_HOUR, "America/Winnipeg",965Calendar.APRIL, 1, -Calendar.SUNDAY, 2*ONE_HOUR, SimpleTimeZone.WALL_TIME,966Calendar.OCTOBER, -1, Calendar.SUNDAY, 2*ONE_HOUR, SimpleTimeZone.STANDARD_TIME,9671*ONE_HOUR);968Calendar cal = Calendar.getInstance(tz, Locale.US);969cal.clear();970cal.set(2039, Calendar.OCTOBER, 1);971cal.getTime();972cal.set(cal.DAY_OF_WEEK, cal.SUNDAY);973cal.set(cal.DAY_OF_WEEK_IN_MONTH, -1);974cal.add(Calendar.HOUR_OF_DAY, 2);975if (cal.get(cal.DST_OFFSET) == 0) {976errln("Should still be in DST.");977}978}979980private static final int ONE_HOUR = 60 * 60 * 1000;981/**982* Returns an instance of SimpleTimeZone for983* "PST". (TimeZone.getTimeZone() no longer returns a984* SimpleTimeZone object.)985* @since 1.4986*/987private SimpleTimeZone getPST() {988return new SimpleTimeZone(-8*ONE_HOUR, "PST",989Calendar.APRIL, 1, -Calendar.SUNDAY, 2*ONE_HOUR,990Calendar.OCTOBER, -1, Calendar.SUNDAY, 2*ONE_HOUR,9911*ONE_HOUR);992}993}994//eof995996997