Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/java/util/Calendar/CalendarRegression.java
47182 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 4031502 4035301 4040996 4051765 4059654 4061476 4070502 4071197 407138526* 4073929 4083167 4086724 4092362 4095407 4096231 4096539 4100311 410327127* 4106136 4108764 4114578 4118384 4125881 4125892 4136399 4141665 414293328* 4145158 4145983 4147269 4149677 4162587 4165343 4166109 4167060 417351629* 4174361 4177484 4197699 4209071 4288792 4328747 4413980 4546637 462399730* 4685354 4655637 4683492 4080631 4080631 4167995 4340146 463940731* 4652815 4652830 4740554 4936355 4738710 4633646 4846659 4822110 496064232* 4973919 4980088 4965624 5013094 5006864 815207733* @library /java/text/testlib34*/3536import java.lang.reflect.*;37import java.io.*;38import java.util.*;39import java.text.*;4041public class CalendarRegression extends IntlTest {4243public static void main(String[] args) throws Exception {44new CalendarRegression().run(args);45}4647/*48Synopsis: java.sql.Timestamp constructor works wrong on Windows 954950==== Here is the test ====51public static void main (String args[]) {52java.sql.Timestamp t= new java.sql.Timestamp(0,15,5,5,8,13,123456700);53logln("expected=1901-04-05 05:08:13.1234567");54logln(" result="+t);55}5657==== Here is the output of the test on Solaris or NT ====58expected=1901-04-05 05:08:13.123456759result=1901-04-05 05:08:13.12345676061==== Here is the output of the test on Windows95 ====62expected=1901-04-05 05:08:13.123456763result=1901-04-05 06:08:13.123456764*/6566public void Test4031502() {67// This bug actually occurs on Windows NT as well, and doesn't68// require the host zone to be set; it can be set in Java.69String[] ids = TimeZone.getAvailableIDs();70boolean bad = false;71for (int i=0; i<ids.length; ++i) {72TimeZone zone = TimeZone.getTimeZone(ids[i]);73GregorianCalendar cal = new GregorianCalendar(zone);74cal.clear();75cal.set(1900, 15, 5, 5, 8, 13);76if (cal.get(Calendar.HOUR) != 5) {77logln(zone.getID() + " " +78//zone.useDaylightTime() + " " +79cal.get(Calendar.DST_OFFSET) / (60*60*1000) + " " +80zone.getRawOffset() / (60*60*1000) +81": HOUR = " + cal.get(Calendar.HOUR));82bad = true;83}84}85if (bad) errln("TimeZone problems with GC");86}8788public void Test4035301() {89GregorianCalendar c = new GregorianCalendar(98, 8, 7);90GregorianCalendar d = new GregorianCalendar(98, 8, 7);91if (c.after(d) ||92c.after(c) ||93c.before(d) ||94c.before(c) ||95!c.equals(c) ||96!c.equals(d))97errln("Fail");98}99100public void Test4040996() {101String[] ids = TimeZone.getAvailableIDs(-8 * 60 * 60 * 1000);102SimpleTimeZone pdt = new SimpleTimeZone(-8 * 60 * 60 * 1000, ids[0]);103pdt.setStartRule(Calendar.APRIL, 1, Calendar.SUNDAY, 2 * 60 * 60 * 1000);104pdt.setEndRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 2 * 60 * 60 * 1000);105Calendar calendar = new GregorianCalendar(pdt);106107calendar.set(Calendar.MONTH,3);108calendar.set(Calendar.DAY_OF_MONTH,18);109calendar.set(Calendar.SECOND, 30);110111logln("MONTH: " + calendar.get(Calendar.MONTH));112logln("DAY_OF_MONTH: " +113calendar.get(Calendar.DAY_OF_MONTH));114logln("MINUTE: " + calendar.get(Calendar.MINUTE));115logln("SECOND: " + calendar.get(Calendar.SECOND));116117calendar.add(Calendar.SECOND,6);118//This will print out todays date for MONTH and DAY_OF_MONTH119//instead of the date it was set to.120//This happens when adding MILLISECOND or MINUTE also121logln("MONTH: " + calendar.get(Calendar.MONTH));122logln("DAY_OF_MONTH: " +123calendar.get(Calendar.DAY_OF_MONTH));124logln("MINUTE: " + calendar.get(Calendar.MINUTE));125logln("SECOND: " + calendar.get(Calendar.SECOND));126if (calendar.get(Calendar.MONTH) != 3 ||127calendar.get(Calendar.DAY_OF_MONTH) != 18 ||128calendar.get(Calendar.SECOND) != 36)129errln("Fail: Calendar.add misbehaves");130}131132public void Test4051765() {133Calendar cal = Calendar.getInstance();134cal.setLenient(false);135cal.set(Calendar.DAY_OF_WEEK, 0);136try {137cal.getTime();138errln("Fail: DAY_OF_WEEK 0 should be disallowed");139}140catch (IllegalArgumentException e) {141return;142}143}144145/* User error - no bug here146public void Test4059524() {147// Create calendar for April 10, 1997148GregorianCalendar calendar = new GregorianCalendar();149// print out a bunch of interesting things150logln("ERA: " + calendar.get(calendar.ERA));151logln("YEAR: " + calendar.get(calendar.YEAR));152logln("MONTH: " + calendar.get(calendar.MONTH));153logln("WEEK_OF_YEAR: " +154calendar.get(calendar.WEEK_OF_YEAR));155logln("WEEK_OF_MONTH: " +156calendar.get(calendar.WEEK_OF_MONTH));157logln("DATE: " + calendar.get(calendar.DATE));158logln("DAY_OF_MONTH: " +159calendar.get(calendar.DAY_OF_MONTH));160logln("DAY_OF_YEAR: " + calendar.get(calendar.DAY_OF_YEAR));161logln("DAY_OF_WEEK: " + calendar.get(calendar.DAY_OF_WEEK));162logln("DAY_OF_WEEK_IN_MONTH: " +163calendar.get(calendar.DAY_OF_WEEK_IN_MONTH));164logln("AM_PM: " + calendar.get(calendar.AM_PM));165logln("HOUR: " + calendar.get(calendar.HOUR));166logln("HOUR_OF_DAY: " + calendar.get(calendar.HOUR_OF_DAY));167logln("MINUTE: " + calendar.get(calendar.MINUTE));168logln("SECOND: " + calendar.get(calendar.SECOND));169logln("MILLISECOND: " + calendar.get(calendar.MILLISECOND));170logln("ZONE_OFFSET: "171+ (calendar.get(calendar.ZONE_OFFSET)/(60*60*1000)));172logln("DST_OFFSET: "173+ (calendar.get(calendar.DST_OFFSET)/(60*60*1000)));174calendar = new GregorianCalendar(1997,3,10);175calendar.getTime();176logln("April 10, 1997");177logln("ERA: " + calendar.get(calendar.ERA));178logln("YEAR: " + calendar.get(calendar.YEAR));179logln("MONTH: " + calendar.get(calendar.MONTH));180logln("WEEK_OF_YEAR: " +181calendar.get(calendar.WEEK_OF_YEAR));182logln("WEEK_OF_MONTH: " +183calendar.get(calendar.WEEK_OF_MONTH));184logln("DATE: " + calendar.get(calendar.DATE));185logln("DAY_OF_MONTH: " +186calendar.get(calendar.DAY_OF_MONTH));187logln("DAY_OF_YEAR: " + calendar.get(calendar.DAY_OF_YEAR));188logln("DAY_OF_WEEK: " + calendar.get(calendar.DAY_OF_WEEK));189logln("DAY_OF_WEEK_IN_MONTH: " + calendar.get(calendar.DAY_OF_WEEK_IN_MONTH));190logln("AM_PM: " + calendar.get(calendar.AM_PM));191logln("HOUR: " + calendar.get(calendar.HOUR));192logln("HOUR_OF_DAY: " + calendar.get(calendar.HOUR_OF_DAY));193logln("MINUTE: " + calendar.get(calendar.MINUTE));194logln("SECOND: " + calendar.get(calendar.SECOND));195logln("MILLISECOND: " + calendar.get(calendar.MILLISECOND));196logln("ZONE_OFFSET: "197+ (calendar.get(calendar.ZONE_OFFSET)/(60*60*1000))); // in hours198logln("DST_OFFSET: "199+ (calendar.get(calendar.DST_OFFSET)/(60*60*1000))); // in hours200}201*/202203public void Test4059654() {204GregorianCalendar gc = new GregorianCalendar();205206gc.set(1997, 3, 1, 15, 16, 17); // April 1, 1997207208gc.set(Calendar.HOUR, 0);209gc.set(Calendar.AM_PM, Calendar.AM);210gc.set(Calendar.MINUTE, 0);211gc.set(Calendar.SECOND, 0);212gc.set(Calendar.MILLISECOND, 0);213214Date cd = gc.getTime();215Date exp = new Date(97, 3, 1, 0, 0, 0);216if (!cd.equals(exp))217errln("Fail: Calendar.set broken. Got " + cd + " Want " + exp);218}219220public void Test4061476() {221SimpleDateFormat fmt = new SimpleDateFormat("ddMMMyy", Locale.UK);222Calendar cal = GregorianCalendar.getInstance(TimeZone.getTimeZone("GMT"),223Locale.UK);224fmt.setCalendar(cal);225try226{227Date date = fmt.parse("29MAY97");228cal.setTime(date);229}230catch (Exception e) {;}231cal.set(Calendar.HOUR_OF_DAY, 13);232logln("Hour: "+cal.get(Calendar.HOUR_OF_DAY));233cal.add(Calendar.HOUR_OF_DAY, 6);234logln("Hour: "+cal.get(Calendar.HOUR_OF_DAY));235if (cal.get(Calendar.HOUR_OF_DAY) != 19)236errln("Fail: Want 19 Got " + cal.get(Calendar.HOUR_OF_DAY));237}238239public void Test4070502() {240Date d = getAssociatedDate(new Date(98, 0, 30));241Calendar cal = new GregorianCalendar();242cal.setTime(d);243if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY ||244cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY)245errln("Fail: Want weekday Got " + d);246}247248/**249* Get the associated date starting from a specified date250* NOTE: the unnecessary "getTime()'s" below are a work-around for a251* bug in jdk 1.1.3 (and probably earlier versions also)252* <p>253* @param date The date to start from254*/255public static Date getAssociatedDate(Date d) {256GregorianCalendar cal = new GregorianCalendar();257cal.setTime(d);258//cal.add(field, amount); //<-- PROBLEM SEEN WITH field = DATE,MONTH259// cal.getTime(); // <--- REMOVE THIS TO SEE BUG260while (true) {261int wd = cal.get(Calendar.DAY_OF_WEEK);262if (wd == Calendar.SATURDAY || wd == Calendar.SUNDAY) {263cal.add(Calendar.DATE, 1);264// cal.getTime();265}266else267break;268}269return cal.getTime();270}271272public void Test4071197() {273dowTest(false);274dowTest(true);275}276277void dowTest(boolean lenient) {278GregorianCalendar cal = new GregorianCalendar();279cal.set(1997, Calendar.AUGUST, 12); // Wednesday280// cal.getTime(); // Force update281cal.setLenient(lenient);282cal.set(1996, Calendar.DECEMBER, 1); // Set the date to be December 1, 1996283int dow = cal.get(Calendar.DAY_OF_WEEK);284int min = cal.getMinimum(Calendar.DAY_OF_WEEK);285int max = cal.getMaximum(Calendar.DAY_OF_WEEK);286logln(cal.getTime().toString());287if (min != Calendar.SUNDAY || max != Calendar.SATURDAY)288errln("FAIL: Min/max bad");289if (dow < min || dow > max)290errln("FAIL: Day of week " + dow + " out of range");291if (dow != Calendar.SUNDAY)292errln("FAIL: Day of week should be SUNDAY Got " + dow);293}294295public void Test4071385() {296Calendar cal = Calendar.getInstance();297cal.setTime(new Date(98, Calendar.JUNE, 24));298cal.set(Calendar.MONTH, Calendar.NOVEMBER); // change a field299logln(cal.getTime().toString());300if (!cal.getTime().equals(new Date(98, Calendar.NOVEMBER, 24)))301errln("Fail");302}303304public void Test4073929() {305GregorianCalendar foo1 = new GregorianCalendar(1997, 8, 27);306foo1.add(Calendar.DAY_OF_MONTH, +1);307int testyear = foo1.get(Calendar.YEAR);308int testmonth = foo1.get(Calendar.MONTH);309int testday = foo1.get(Calendar.DAY_OF_MONTH);310if (testyear != 1997 ||311testmonth != 8 ||312testday != 28)313errln("Fail: Calendar not initialized");314}315316public void Test4083167() {317TimeZone saveZone = TimeZone.getDefault();318try {319TimeZone.setDefault(TimeZone.getTimeZone("UTC"));320Date firstDate = new Date();321Calendar cal = new GregorianCalendar();322cal.setTime(firstDate);323long firstMillisInDay = cal.get(Calendar.HOUR_OF_DAY) * 3600000L +324cal.get(Calendar.MINUTE) * 60000L +325cal.get(Calendar.SECOND) * 1000L +326cal.get(Calendar.MILLISECOND);327328logln("Current time: " + firstDate.toString());329330for (int validity=0; validity<30; validity++) {331Date lastDate = new Date(firstDate.getTime() +332(long)validity*1000*24*60*60);333cal.setTime(lastDate);334long millisInDay = cal.get(Calendar.HOUR_OF_DAY) * 3600000L +335cal.get(Calendar.MINUTE) * 60000L +336cal.get(Calendar.SECOND) * 1000L +337cal.get(Calendar.MILLISECOND);338if (firstMillisInDay != millisInDay) {339errln("Day has shifted " + lastDate);340}341}342}343finally {344TimeZone.setDefault(saveZone);345}346}347348public void Test4086724() {349SimpleDateFormat date;350TimeZone saveZone = TimeZone.getDefault();351Locale saveLocale = Locale.getDefault();352353String summerTime = "British Summer Time";354String standardTime = "Greenwich Mean Time";355try {356Locale.setDefault(Locale.UK);357TimeZone.setDefault(TimeZone.getTimeZone("Europe/London"));358date = new SimpleDateFormat("zzzz");359360Calendar cal=Calendar.getInstance();361cal.set(1997,Calendar.SEPTEMBER,30);362Date now=cal.getTime();363String formattedDate = date.format(now);364if (!formattedDate.equals(summerTime)) {365errln("Wrong display name \"" + formattedDate366+ "\" for <" + now + ">");367}368int weekOfYear = cal.get(Calendar.WEEK_OF_YEAR);369if (weekOfYear != 40) {370errln("Wrong week-of-year " + weekOfYear371+ " for <" + now + ">");372}373374cal.set(1996,Calendar.DECEMBER,31);375now=cal.getTime();376formattedDate = date.format(now);377if (!formattedDate.equals(standardTime)) {378errln("Wrong display name \"" + formattedDate379+ "\" for <" + now + ">");380}381weekOfYear = cal.get(Calendar.WEEK_OF_YEAR);382if (weekOfYear != 1) {383errln("Wrong week-of-year " + weekOfYear384+ " for <" + now + ">");385}386387cal.set(1997,Calendar.JANUARY,1);388now=cal.getTime();389formattedDate = date.format(now);390if (!formattedDate.equals(standardTime)) {391errln("Wrong display name \"" + formattedDate392+ "\" for <" + now + ">");393}394weekOfYear = cal.get(Calendar.WEEK_OF_YEAR);395if (weekOfYear != 1) {396errln("Wrong week-of-year " + weekOfYear397+ " for <" + now + ">");398}399400cal.set(1997,Calendar.JANUARY,8);401now=cal.getTime();402formattedDate = date.format(now);403if (!formattedDate.equals(standardTime)) {404errln("Wrong display name \"" + formattedDate405+ "\" for <" + now + ">");406}407weekOfYear = cal.get(Calendar.WEEK_OF_YEAR);408if (weekOfYear != 2) {409errln("Wrong week-of-year " + weekOfYear410+ " for <" + now + ">");411}412413}414finally {415Locale.setDefault(saveLocale);416TimeZone.setDefault(saveZone);417}418}419420public void Test4092362() {421GregorianCalendar cal1 = new GregorianCalendar(1997, 10, 11, 10, 20, 40);422/*cal1.set( Calendar.YEAR, 1997 );423cal1.set( Calendar.MONTH, 10 );424cal1.set( Calendar.DATE, 11 );425cal1.set( Calendar.HOUR, 10 );426cal1.set( Calendar.MINUTE, 20 );427cal1.set( Calendar.SECOND, 40 ); */428429logln( " Cal1 = " + cal1.getTime().getTime() );430logln( " Cal1 time in ms = " + cal1.get(Calendar.MILLISECOND) );431for( int k = 0; k < 100 ; k++ );432433GregorianCalendar cal2 = new GregorianCalendar(1997, 10, 11, 10, 20, 40);434/*cal2.set( Calendar.YEAR, 1997 );435cal2.set( Calendar.MONTH, 10 );436cal2.set( Calendar.DATE, 11 );437cal2.set( Calendar.HOUR, 10 );438cal2.set( Calendar.MINUTE, 20 );439cal2.set( Calendar.SECOND, 40 ); */440441logln( " Cal2 = " + cal2.getTime().getTime() );442logln( " Cal2 time in ms = " + cal2.get(Calendar.MILLISECOND) );443if( !cal1.equals( cal2 ) )444errln("Fail: Milliseconds randomized");445}446447public void Test4095407() {448GregorianCalendar a = new GregorianCalendar(1997,Calendar.NOVEMBER, 13);449int dow = a.get(Calendar.DAY_OF_WEEK);450if (dow != Calendar.THURSDAY)451errln("Fail: Want THURSDAY Got " + dow);452}453454public void Test4096231() {455TimeZone GMT = TimeZone.getTimeZone("GMT");456TimeZone PST = TimeZone.getTimeZone("PST");457int sec = 0, min = 0, hr = 0, day = 1, month = 10, year = 1997;458459Calendar cal1 = new GregorianCalendar(PST);460cal1.setTime(new Date(880698639000L));461int p;462logln("PST 1 is: " + (p=cal1.get(cal1.HOUR_OF_DAY)));463cal1.setTimeZone(GMT);464// Issue 1: Changing the timezone doesn't change the465// represented time.466int h1,h2;467logln("GMT 1 is: " + (h1=cal1.get(cal1.HOUR_OF_DAY)));468cal1.setTime(new Date(880698639000L));469logln("GMT 2 is: " + (h2=cal1.get(cal1.HOUR_OF_DAY)));470// Note: This test had a bug in it. It wanted h1!=h2, when471// what was meant was h1!=p. Fixed this concurrent with fix472// to 4177484.473if (p == h1 || h1 != h2)474errln("Fail: Hour same in different zones");475476Calendar cal2 = new GregorianCalendar(GMT);477Calendar cal3 = new GregorianCalendar(PST);478cal2.set(Calendar.MILLISECOND, 0);479cal3.set(Calendar.MILLISECOND, 0);480481cal2.set(cal1.get(cal1.YEAR),482cal1.get(cal1.MONTH),483cal1.get(cal1.DAY_OF_MONTH),484cal1.get(cal1.HOUR_OF_DAY),485cal1.get(cal1.MINUTE),486cal1.get(cal1.SECOND));487488long t1,t2,t3,t4;489logln("RGMT 1 is: " + (t1=cal2.getTime().getTime()));490cal3.set(year, month, day, hr, min, sec);491logln("RPST 1 is: " + (t2=cal3.getTime().getTime()));492cal3.setTimeZone(GMT);493logln("RGMT 2 is: " + (t3=cal3.getTime().getTime()));494cal3.set(cal1.get(cal1.YEAR),495cal1.get(cal1.MONTH),496cal1.get(cal1.DAY_OF_MONTH),497cal1.get(cal1.HOUR_OF_DAY),498cal1.get(cal1.MINUTE),499cal1.get(cal1.SECOND));500// Issue 2: Calendar continues to use the timezone in its501// constructor for set() conversions, regardless502// of calls to setTimeZone()503logln("RGMT 3 is: " + (t4=cal3.getTime().getTime()));504if (t1 == t2 ||505t1 != t4 ||506t2 != t3)507errln("Fail: Calendar zone behavior faulty");508}509510public void Test4096539() {511int[] y = {31,28,31,30,31,30,31,31,30,31,30,31};512513for (int x=0;x<12;x++) {514GregorianCalendar gc = new515GregorianCalendar(1997,x,y[x]);516int m1,m2;517log((m1=gc.get(Calendar.MONTH)+1)+"/"+518gc.get(Calendar.DATE)+"/"+gc.get(Calendar.YEAR)+519" + 1mo = ");520521gc.add(Calendar.MONTH, 1);522logln((m2=gc.get(Calendar.MONTH)+1)+"/"+523gc.get(Calendar.DATE)+"/"+gc.get(Calendar.YEAR)524);525int m = (m1 % 12) + 1;526if (m2 != m)527errln("Fail: Want " + m + " Got " + m2);528}529530}531532public void Test4100311() {533GregorianCalendar cal = (GregorianCalendar)Calendar.getInstance();534cal.set(Calendar.YEAR, 1997);535cal.set(Calendar.DAY_OF_YEAR, 1);536Date d = cal.getTime(); // Should be Jan 1537logln(d.toString());538if (cal.get(Calendar.DAY_OF_YEAR) != 1)539errln("Fail: DAY_OF_YEAR not set");540}541542public void Test4103271() {543if (Locale.getDefault().equals(new Locale("th", "TH"))) {544return;545}546547SimpleDateFormat sdf = new SimpleDateFormat();548int numYears=40, startYear=1997, numDays=15;549String output, testDesc;550GregorianCalendar testCal = (GregorianCalendar)Calendar.getInstance();551testCal.clear();552sdf.setCalendar(testCal);553sdf.applyPattern("d MMM yyyy");554boolean fail = false;555for (int firstDay=1; firstDay<=2; firstDay++) {556for (int minDays=1; minDays<=7; minDays++) {557testCal.setMinimalDaysInFirstWeek(minDays);558testCal.setFirstDayOfWeek(firstDay);559testDesc = ("Test" + String.valueOf(firstDay) + String.valueOf(minDays));560logln(testDesc + " => 1st day of week=" +561String.valueOf(firstDay) +562", minimum days in first week=" +563String.valueOf(minDays));564for (int j=startYear; j<=startYear+numYears; j++) {565testCal.set(j,11,25);566for(int i=0; i<numDays; i++) {567testCal.add(Calendar.DATE,1);568String calWOY;569int actWOY = testCal.get(Calendar.WEEK_OF_YEAR);570if (actWOY < 1 || actWOY > 53) {571Date d = testCal.getTime();572calWOY = String.valueOf(actWOY);573output = testDesc + " - " + sdf.format(d) + "\t";574output = output + "\t" + calWOY;575logln(output);576fail = true;577}578}579}580}581}582583int[] DATA = {5843, 52, 52, 52, 52, 52, 52, 52,5851, 1, 1, 1, 1, 1, 1,5862, 2, 2, 2, 2, 2, 2,5874, 52, 52, 52, 52, 52, 52, 52,58853, 53, 53, 53, 53, 53, 53,5891, 1, 1, 1, 1, 1, 1,590};591testCal.setFirstDayOfWeek(Calendar.SUNDAY);592for (int j=0; j<DATA.length; j+=22) {593logln("Minimal days in first week = " + DATA[j] +594" Week starts on Sunday");595testCal.setMinimalDaysInFirstWeek(DATA[j]);596testCal.set(1997, Calendar.DECEMBER, 21);597for (int i=0; i<21; ++i) {598int woy = testCal.get(Calendar.WEEK_OF_YEAR);599log("\t" + testCal.getTime() + " " + woy);600if (woy != DATA[j + 1 + i]) {601log(" ERROR");602fail = true;603} else {604logln(" OK");605}606607// Now compute the time from the fields, and make sure we608// get the same answer back. This is a round-trip test.609Date save = testCal.getTime();610testCal.clear();611testCal.set(Calendar.YEAR, DATA[j+1+i] < 25 ? 1998 : 1997);612testCal.set(Calendar.WEEK_OF_YEAR, DATA[j+1+i]);613testCal.set(Calendar.DAY_OF_WEEK, (i%7) + Calendar.SUNDAY);614if (!testCal.getTime().equals(save)) {615logln(" Parse failed: " + testCal.getTime());616fail= true;617} else {618logln(" Passed");619}620621testCal.setTime(save);622testCal.add(Calendar.DAY_OF_MONTH, 1);623}624}625626// Test field disambiguation with a few special hard-coded cases.627// This shouldn't fail if the above cases aren't failing.628Object[] DISAM = {629new Integer(1998), new Integer(1), new Integer(Calendar.SUNDAY),630new Date(97, Calendar.DECEMBER, 28),631new Integer(1998), new Integer(2), new Integer(Calendar.SATURDAY),632new Date(98, Calendar.JANUARY, 10),633new Integer(1998), new Integer(53), new Integer(Calendar.THURSDAY),634new Date(98, Calendar.DECEMBER, 31),635new Integer(1998), new Integer(53), new Integer(Calendar.FRIDAY),636new Date(99, Calendar.JANUARY, 1),637};638testCal.setMinimalDaysInFirstWeek(3);639testCal.setFirstDayOfWeek(Calendar.SUNDAY);640for (int i=0; i<DISAM.length; i+=4) {641int y = ((Integer)DISAM[i]).intValue();642int woy = ((Integer)DISAM[i+1]).intValue();643int dow = ((Integer)DISAM[i+2]).intValue();644Date exp = (Date)DISAM[i+3];645testCal.clear();646testCal.set(Calendar.YEAR, y);647testCal.set(Calendar.WEEK_OF_YEAR, woy);648testCal.set(Calendar.DAY_OF_WEEK, dow);649log(y + "-W" + woy + "-DOW" + dow);650if (!testCal.getTime().equals(exp)) {651logln(" FAILED expect: " + exp + "\n got: " +testCal.getTime());652fail = true;653} else {654logln(" OK");655}656}657658// Now try adding and rolling659Object ADD = new Object();660Object ROLL = new Object();661Object[] ADDROLL = {662ADD, new Integer(1), new Date(98, Calendar.DECEMBER, 25), new Date(99, Calendar.JANUARY, 1),663ADD, new Integer(1), new Date(97, Calendar.DECEMBER, 28), new Date(98, Calendar.JANUARY, 4),664ROLL, new Integer(1), new Date(98, Calendar.DECEMBER, 27), new Date(98, Calendar.JANUARY, 4),665ROLL, new Integer(1), new Date(99, Calendar.DECEMBER, 24), new Date(99, Calendar.DECEMBER, 31),666ROLL, new Integer(1), new Date(99, Calendar.DECEMBER, 25), new Date(99, Calendar.JANUARY, 9),667};668testCal.setMinimalDaysInFirstWeek(3);669testCal.setFirstDayOfWeek(Calendar.SUNDAY);670for (int i=0; i<ADDROLL.length; i+=4) {671int amount = ((Integer)ADDROLL[i+1]).intValue();672Date before = (Date)ADDROLL[i+2];673Date after = (Date)ADDROLL[i+3];674675testCal.setTime(before);676if (ADDROLL[i] == ADD)677testCal.add(Calendar.WEEK_OF_YEAR, amount);678else679testCal.roll(Calendar.WEEK_OF_YEAR, amount);680log((ADDROLL[i]==ADD ? "add(WOY," : "roll(WOY,") +681amount + ")\t " + before +682"\n\t\t => " + testCal.getTime());683if (!after.equals(testCal.getTime())) {684logln("\tFAIL\n\t\texp: " + after);685fail = true;686} else687logln(" OK");688689testCal.setTime(after);690if (ADDROLL[i] == ADD)691testCal.add(Calendar.WEEK_OF_YEAR, -amount);692else693testCal.roll(Calendar.WEEK_OF_YEAR, -amount);694log((ADDROLL[i]==ADD ? "add(WOY," : "roll(WOY,") +695(-amount) + ") " + after +696"\n\t\t => " + testCal.getTime());697if (!before.equals(testCal.getTime())) {698logln("\tFAIL\n\t\texp: " + before);699fail = true;700}701else logln("\tOK");702}703704if (fail) {705errln("Fail: Week of year misbehaving");706}707}708709public void Test4106136() {710Locale saveLocale = Locale.getDefault();711try {712Locale[] locales = { Locale.CHINESE, Locale.CHINA };713for (int i=0; i<locales.length; ++i) {714Locale.setDefault(locales[i]);715int[] n = {716Calendar.getAvailableLocales().length,717DateFormat.getAvailableLocales().length,718NumberFormat.getAvailableLocales().length719};720for (int j=0; j<n.length; ++j) {721if (n[j] == 0) {722errln("Fail: No locales for " + locales[i]);723}724}725}726}727finally {728Locale.setDefault(saveLocale);729}730}731732public void Test4108764() {733Date d00 = new Date(97, Calendar.MARCH, 15, 12, 00, 00);734Date d01 = new Date(97, Calendar.MARCH, 15, 12, 00, 56);735Date d10 = new Date(97, Calendar.MARCH, 15, 12, 34, 00);736Date d11 = new Date(97, Calendar.MARCH, 15, 12, 34, 56);737Date epoch = new Date(70, Calendar.JANUARY, 1);738739Calendar cal = Calendar.getInstance();740cal.setTime(d11);741742cal.clear( Calendar.MINUTE );743logln(cal.getTime().toString());744if (!cal.getTime().equals(d01))745errln("Fail: clear(MINUTE) broken");746747cal.set( Calendar.SECOND, 0 );748logln(cal.getTime().toString());749if (!cal.getTime().equals(d00))750errln("Fail: set(SECOND, 0) broken");751752cal.setTime(d11);753cal.set( Calendar.SECOND, 0 );754logln(cal.getTime().toString());755if (!cal.getTime().equals(d10))756errln("Fail: set(SECOND, 0) broken #2");757758cal.clear( Calendar.MINUTE );759logln(cal.getTime().toString());760if (!cal.getTime().equals(d00))761errln("Fail: clear(MINUTE) broken #2");762763cal.clear();764logln(cal.getTime().toString());765if (!cal.getTime().equals(epoch))766errln("Fail: clear() broken Want " + epoch);767}768769public void Test4114578() {770int ONE_HOUR = 60*60*1000;771TimeZone saveZone = TimeZone.getDefault();772boolean fail = false;773try {774TimeZone.setDefault(TimeZone.getTimeZone("PST"));775Calendar cal = Calendar.getInstance();776long onset = new Date(98, Calendar.APRIL, 5, 1, 0).getTime() + ONE_HOUR;777long cease = new Date(98, Calendar.OCTOBER, 25, 0, 0).getTime() + 2*ONE_HOUR;778779final int ADD = 1;780final int ROLL = 2;781782long[] DATA = {783// Start Action Amt Expected_change784onset - ONE_HOUR, ADD, 1, ONE_HOUR,785onset, ADD, -1, -ONE_HOUR,786onset - ONE_HOUR, ROLL, 1, ONE_HOUR,787onset, ROLL, -1, -ONE_HOUR,788cease - ONE_HOUR, ADD, 1, ONE_HOUR,789cease, ADD, -1, -ONE_HOUR,790// roll() was changed to support wall-clock-based roll (JDK-8152077). The791// time value may jump 2 hours by skipping non-existent wall-clock time.792// Note that JDK-4114578 was a problem of add(), not roll().793cease - ONE_HOUR, ROLL, 1, ONE_HOUR * 2,794cease, ROLL, -1, -ONE_HOUR * 2,795};796797for (int i=0; i<DATA.length; i+=4) {798Date date = new Date(DATA[i]);799int amt = (int) DATA[i+2];800long expectedChange = DATA[i+3];801802log(date.toString());803cal.setTime(date);804805switch ((int) DATA[i+1]) {806case ADD:807log(" add (HOUR," + (amt<0?"":"+")+amt + ")= ");808cal.add(Calendar.HOUR, amt);809break;810case ROLL:811log(" roll(HOUR," + (amt<0?"":"+")+amt + ")= ");812cal.roll(Calendar.HOUR, amt);813break;814}815816log(cal.getTime().toString());817818long change = cal.getTime().getTime() - date.getTime();819if (change != expectedChange) {820fail = true;821logln(" FAIL");822}823else logln(" OK");824}825} finally {826TimeZone.setDefault(saveZone);827}828829if (fail) {830errln("Fail: roll/add misbehaves around DST onset/cease");831}832}833834/**835* Make sure maximum for HOUR field is 11, not 12.836*/837public void Test4118384() {838Calendar cal = Calendar.getInstance();839if (cal.getMaximum(Calendar.HOUR) != 11 ||840cal.getLeastMaximum(Calendar.HOUR) != 11 ||841cal.getActualMaximum(Calendar.HOUR) != 11)842errln("Fail: maximum of HOUR field should be 11");843}844845/**846* Check isLeapYear for BC years.847*/848public void Test4125881() {849GregorianCalendar cal = (GregorianCalendar) Calendar.getInstance();850DateFormat fmt = new SimpleDateFormat("MMMM d, yyyy G");851cal.clear();852for (int y=-20; y<=10; ++y) {853cal.set(Calendar.ERA, y < 1 ? GregorianCalendar.BC : GregorianCalendar.AD);854cal.set(Calendar.YEAR, y < 1 ? 1 - y : y);855logln(y + " = " + fmt.format(cal.getTime()) + " " +856cal.isLeapYear(y));857if (cal.isLeapYear(y) != ((y+40)%4 == 0))858errln("Leap years broken");859}860}861862/**863* Prove that GregorianCalendar is proleptic (it used to cut off864* at 45 BC, and not have leap years before then).865*/866public void Test4125892() {867if (Locale.getDefault().equals(new Locale("th", "TH"))) {868return;869}870871GregorianCalendar cal = (GregorianCalendar) Calendar.getInstance();872DateFormat fmt = new SimpleDateFormat("MMMM d, yyyy G");873cal.clear();874cal.set(Calendar.ERA, GregorianCalendar.BC);875cal.set(Calendar.YEAR, 81); // 81 BC is a leap year (proleptically)876cal.set(Calendar.MONTH, Calendar.FEBRUARY);877cal.set(Calendar.DATE, 28);878cal.add(Calendar.DATE, 1);879if (cal.get(Calendar.DATE) != 29 ||880!cal.isLeapYear(-80)) // -80 == 81 BC881errln("Calendar not proleptic");882}883884/**885* Calendar and GregorianCalendar hashCode() methods need improvement.886* Calendar needs a good implementation that subclasses can override,887* and GregorianCalendar should use that implementation.888*/889public void Test4136399() {890/* Note: This test is actually more strict than it has to be.891* Technically, there is no requirement that unequal objects have892* unequal hashes. We only require equal objects to have equal hashes.893* It is desirable for unequal objects to have distributed hashes, but894* there is no hard requirement here.895*896* In this test we make assumptions about certain attributes of calendar897* objects getting represented in the hash, which need not always be the898* case (although it does work currently with the given test). */899Calendar a = Calendar.getInstance();900Calendar b = (Calendar)a.clone();901if (a.hashCode() != b.hashCode()) {902errln("Calendar hash code unequal for cloned objects");903}904905b.setMinimalDaysInFirstWeek(7 - a.getMinimalDaysInFirstWeek());906if (a.hashCode() == b.hashCode()) {907errln("Calendar hash code ignores minimal days in first week");908}909b.setMinimalDaysInFirstWeek(a.getMinimalDaysInFirstWeek());910911b.setFirstDayOfWeek((a.getFirstDayOfWeek() % 7) + 1); // Next day912if (a.hashCode() == b.hashCode()) {913errln("Calendar hash code ignores first day of week");914}915b.setFirstDayOfWeek(a.getFirstDayOfWeek());916917b.setLenient(!a.isLenient());918if (a.hashCode() == b.hashCode()) {919errln("Calendar hash code ignores lenient setting");920}921b.setLenient(a.isLenient());922923// Assume getTimeZone() returns a reference, not a clone924// of a reference -- this is true as of this writing925b.getTimeZone().setRawOffset(a.getTimeZone().getRawOffset() + 60*60*1000);926if (a.hashCode() == b.hashCode()) {927errln("Calendar hash code ignores zone");928}929b.getTimeZone().setRawOffset(a.getTimeZone().getRawOffset());930931GregorianCalendar c = new GregorianCalendar();932GregorianCalendar d = (GregorianCalendar)c.clone();933if (c.hashCode() != d.hashCode()) {934errln("GregorianCalendar hash code unequal for clones objects");935}936Date cutover = c.getGregorianChange();937d.setGregorianChange(new Date(cutover.getTime() + 24*60*60*1000));938if (c.hashCode() == d.hashCode()) {939errln("GregorianCalendar hash code ignores cutover");940}941}942943/**944* GregorianCalendar.equals() ignores cutover date945*/946public void Test4141665() {947GregorianCalendar cal = new GregorianCalendar();948GregorianCalendar cal2 = (GregorianCalendar)cal.clone();949Date cut = cal.getGregorianChange();950Date cut2 = new Date(cut.getTime() + 100*24*60*60*1000L); // 100 days later951if (!cal.equals(cal2)) {952errln("Cloned GregorianCalendars not equal");953}954cal2.setGregorianChange(cut2);955if (cal.equals(cal2)) {956errln("GregorianCalendar.equals() ignores cutover");957}958}959960/**961* Bug states that ArrayIndexOutOfBoundsException is thrown by GregorianCalendar.roll()962* when IllegalArgumentException should be.963*/964public void Test4142933() {965GregorianCalendar calendar = new GregorianCalendar();966try {967calendar.roll(-1, true);968errln("Test failed, no exception trown");969}970catch (IllegalArgumentException e) {971// OK: Do nothing972// logln("Test passed");973}974catch (Exception e) {975errln("Test failed. Unexpected exception is thrown: " + e);976e.printStackTrace();977}978}979980/**981* GregorianCalendar handling of Dates Long.MIN_VALUE and Long.MAX_VALUE is982* confusing; unless the time zone has a raw offset of zero, one or the983* other of these will wrap. We've modified the test given in the bug984* report to therefore only check the behavior of a calendar with a zero raw985* offset zone.986*/987public void Test4145158() {988GregorianCalendar calendar = new GregorianCalendar();989990calendar.setTimeZone(TimeZone.getTimeZone("GMT"));991992calendar.setTime(new Date(Long.MIN_VALUE));993int year1 = calendar.get(Calendar.YEAR);994int era1 = calendar.get(Calendar.ERA);995996calendar.setTime(new Date(Long.MAX_VALUE));997int year2 = calendar.get(Calendar.YEAR);998int era2 = calendar.get(Calendar.ERA);9991000if (year1 == year2 && era1 == era2) {1001errln("Fail: Long.MIN_VALUE or Long.MAX_VALUE wrapping around");1002}1003}10041005/**1006* Maximum value for YEAR field wrong.1007*/1008public void Test4145983() {1009GregorianCalendar calendar = new GregorianCalendar();1010calendar.setTimeZone(TimeZone.getTimeZone("GMT"));1011Date[] DATES = { new Date(Long.MAX_VALUE), new Date(Long.MIN_VALUE) };1012for (int i=0; i<DATES.length; ++i) {1013calendar.setTime(DATES[i]);1014int year = calendar.get(Calendar.YEAR);1015int maxYear = calendar.getMaximum(Calendar.YEAR);1016if (year > maxYear) {1017errln("Failed for "+DATES[i].getTime()+" ms: year=" +1018year + ", maxYear=" + maxYear);1019}1020}1021}10221023/**1024* This is a bug in the validation code of GregorianCalendar. As reported,1025* the bug seems worse than it really is, due to a bug in the way the bug1026* report test was written. In reality the bug is restricted to the DAY_OF_YEAR1027* field. - liu 6/29/981028*/1029public void Test4147269() {1030final String[] fieldName = {1031"ERA",1032"YEAR",1033"MONTH",1034"WEEK_OF_YEAR",1035"WEEK_OF_MONTH",1036"DAY_OF_MONTH",1037"DAY_OF_YEAR",1038"DAY_OF_WEEK",1039"DAY_OF_WEEK_IN_MONTH",1040"AM_PM",1041"HOUR",1042"HOUR_OF_DAY",1043"MINUTE",1044"SECOND",1045"MILLISECOND",1046"ZONE_OFFSET",1047"DST_OFFSET"1048};1049GregorianCalendar calendar = new GregorianCalendar();1050calendar.setLenient(false);1051Date date = new Date(1996-1900, Calendar.JANUARY, 3); // Arbitrary date1052for (int field = 0; field < Calendar.FIELD_COUNT; field++) {1053calendar.setTime(date);1054// Note: In the bug report, getActualMaximum() was called instead1055// of getMaximum() -- this was an error. The validation code doesn't1056// use getActualMaximum(), since that's too costly.1057int max = calendar.getMaximum(field);1058int value = max+1;1059calendar.set(field, value);1060try {1061calendar.getTime(); // Force time computation1062// We expect an exception to be thrown. If we fall through1063// to the next line, then we have a bug.1064errln("Test failed with field " + fieldName[field] +1065", date before: " + date +1066", date after: " + calendar.getTime() +1067", value: " + value + " (max = " + max +")");1068} catch (IllegalArgumentException e) {}1069}1070}10711072/**1073* Reported bug is that a GregorianCalendar with a cutover of Date(Long.MAX_VALUE)1074* doesn't behave as a pure Julian calendar.1075* CANNOT REPRODUCE THIS BUG1076*/1077public void Test4149677() {1078TimeZone[] zones = { TimeZone.getTimeZone("GMT"),1079TimeZone.getTimeZone("PST"),1080TimeZone.getTimeZone("EAT") };1081for (int i=0; i<zones.length; ++i) {1082GregorianCalendar calendar = new GregorianCalendar(zones[i]);10831084// Make sure extreme values don't wrap around1085calendar.setTime(new Date(Long.MIN_VALUE));1086if (calendar.get(Calendar.ERA) != GregorianCalendar.BC) {1087errln("Fail: Date(Long.MIN_VALUE) has an AD year in " + zones[i]);1088}1089calendar.setTime(new Date(Long.MAX_VALUE));1090if (calendar.get(Calendar.ERA) != GregorianCalendar.AD) {1091errln("Fail: Date(Long.MAX_VALUE) has a BC year in " + zones[i]);1092}10931094calendar.setGregorianChange(new Date(Long.MAX_VALUE));1095// to obtain a pure Julian calendar10961097boolean is100Leap = calendar.isLeapYear(100);1098if (!is100Leap) {1099errln("test failed with zone " + zones[i].getID());1100errln(" cutover date is Date(Long.MAX_VALUE)");1101errln(" isLeapYear(100) returns: " + is100Leap);1102}1103}1104}11051106/**1107* Calendar and Date HOUR broken. If HOUR is out-of-range, Calendar1108* and Date classes will misbehave.1109*/1110public void Test4162587() {1111TimeZone savedTz = TimeZone.getDefault();1112TimeZone tz = TimeZone.getTimeZone("PST");1113TimeZone.setDefault(tz);1114GregorianCalendar cal = new GregorianCalendar(tz);1115Date d;11161117try {1118for (int i=0; i<5; ++i) {1119if (i>0) logln("---");11201121cal.clear();1122cal.set(1998, Calendar.APRIL, 5, i, 0);1123d = cal.getTime();1124String s0 = d.toString();1125logln("0 " + i + ": " + s0);11261127cal.clear();1128cal.set(1998, Calendar.APRIL, 4, i+24, 0);1129d = cal.getTime();1130String sPlus = d.toString();1131logln("+ " + i + ": " + sPlus);11321133cal.clear();1134cal.set(1998, Calendar.APRIL, 6, i-24, 0);1135d = cal.getTime();1136String sMinus = d.toString();1137logln("- " + i + ": " + sMinus);11381139if (!s0.equals(sPlus) || !s0.equals(sMinus)) {1140errln("Fail: All three lines must match");1141}1142}1143}1144finally {1145TimeZone.setDefault(savedTz);1146}1147}11481149/**1150* Adding 12 months behaves differently from adding 1 year1151*/1152public void Test4165343() {1153GregorianCalendar calendar = new GregorianCalendar(1996, Calendar.FEBRUARY, 29);1154Date start = calendar.getTime();1155logln("init date: " + start);1156calendar.add(Calendar.MONTH, 12);1157Date date1 = calendar.getTime();1158logln("after adding 12 months: " + date1);1159calendar.setTime(start);1160calendar.add(Calendar.YEAR, 1);1161Date date2 = calendar.getTime();1162logln("after adding one year : " + date2);1163if (date1.equals(date2)) {1164logln("Test passed");1165} else {1166errln("Test failed");1167}1168}11691170/**1171* GregorianCalendar.getActualMaximum() does not account for first day of week.1172*/1173public void Test4166109() {1174/* Test month:1175*1176* March 19981177* Su Mo Tu We Th Fr Sa1178* 1 2 3 4 5 6 71179* 8 9 10 11 12 13 141180* 15 16 17 18 19 20 211181* 22 23 24 25 26 27 281182* 29 30 311183*/1184boolean passed = true;1185int field = Calendar.WEEK_OF_MONTH;11861187GregorianCalendar calendar = new GregorianCalendar(Locale.US);1188calendar.set(1998, Calendar.MARCH, 1);1189calendar.setMinimalDaysInFirstWeek(1);1190logln("Date: " + calendar.getTime());11911192int firstInMonth = calendar.get(Calendar.DAY_OF_MONTH);11931194for (int firstInWeek = Calendar.SUNDAY; firstInWeek <= Calendar.SATURDAY; firstInWeek++) {1195calendar.setFirstDayOfWeek(firstInWeek);1196int returned = calendar.getActualMaximum(field);1197int expected = (31 + ((firstInMonth - firstInWeek + 7)% 7) + 6) / 7;11981199logln("First day of week = " + firstInWeek +1200" getActualMaximum(WEEK_OF_MONTH) = " + returned +1201" expected = " + expected +1202((returned == expected) ? " ok" : " FAIL"));12031204if (returned != expected) {1205passed = false;1206}1207}1208if (!passed) {1209errln("Test failed");1210}1211}12121213/**1214* Calendar.getActualMaximum(YEAR) works wrong.1215*1216* Note: Before 1.5, this test case assumed that1217* setGregorianChange didn't change object's date. But it was1218* changed. See 4928615.1219*/1220public void Test4167060() {1221int field = Calendar.YEAR;1222DateFormat format = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy G",1223Locale.US);12241225int[][] dates = {1226// year, month, day of month1227{ 100, Calendar.NOVEMBER, 1 },1228{ -99 /*100BC*/, Calendar.JANUARY, 1 },1229{ 1996, Calendar.FEBRUARY, 29 }};12301231String[] id = { "Hybrid", "Gregorian", "Julian" };12321233for (int k=0; k<3; ++k) {1234logln("--- " + id[k] + " ---");12351236for (int j = 0; j < dates.length; ++j) {1237GregorianCalendar calendar = new GregorianCalendar();1238if (k == 1) {1239calendar.setGregorianChange(new Date(Long.MIN_VALUE));1240} else if (k == 2) {1241calendar.setGregorianChange(new Date(Long.MAX_VALUE));1242}1243calendar.set(dates[j][0], dates[j][1], dates[j][2]);1244format.setCalendar((Calendar)calendar.clone());12451246Date dateBefore = calendar.getTime();12471248int maxYear = calendar.getActualMaximum(field);1249logln("maxYear: " + maxYear + " for " + format.format(calendar.getTime()));1250logln("date before: " + format.format(dateBefore));12511252int years[] = {2000, maxYear-1, maxYear, maxYear+1};12531254for (int i = 0; i < years.length; i++) {1255boolean valid = years[i] <= maxYear;1256calendar.set(field, years[i]);1257Date dateAfter = calendar.getTime();1258int newYear = calendar.get(field);1259calendar.setTime(dateBefore); // restore calendar for next use12601261logln(" Year " + years[i] + (valid? " ok " : " bad") +1262" => " + format.format(dateAfter));1263if (valid && newYear != years[i]) {1264errln(" FAIL: " + newYear + " should be valid; date, month and time shouldn't change");1265} else if (!valid && newYear == years[i]) {1266errln(" FAIL: " + newYear + " should be invalid");1267}1268}1269}1270}1271}12721273/**1274* Calendar.roll broken1275* This bug relies on the TimeZone bug 4173604 to also be fixed.1276*/1277public void Test4173516() {1278if (Locale.getDefault().equals(new Locale("th", "TH"))) {1279return;1280}12811282int fieldsList[][] = {1283{ 1997, Calendar.FEBRUARY, 1, 10, 45, 15, 900 },1284{ 1999, Calendar.DECEMBER, 22, 23, 59, 59, 999 },1285// test case for 4960642 with default cutover1286{ 1582, Calendar.OCTOBER, 4, 23, 59, 59, 999 },1287};1288String[] fieldNames = {1289"ERA", "YEAR", "MONTH", "WEEK_OF_YEAR", "WEEK_OF_MONTH",1290"DAY_OF_MONTH", "DAY_OF_YEAR", "DAY_OF_WEEK", "DAY_OF_WEEK_IN_MONTH",1291"AM_PM", "HOUR", "HOUR_OF_DAY", "MINUTE", "SECOND", "MILLISECOND",1292"ZONE_OFFSET", "DST_OFFSET"1293};12941295Locale savedLocale = Locale.getDefault();1296Locale.setDefault(Locale.US);1297int limit = 40;12981299try {1300GregorianCalendar cal = new GregorianCalendar();13011302cal.setTime(new Date(0));1303cal.roll(Calendar.HOUR, 0x7F000000);1304cal.roll(Calendar.HOUR, -0x7F000000);1305if (cal.getTime().getTime() != 0) {1306errln("Hour rolling broken. expected 0, got "+cal.getTime().getTime());1307}13081309for (int op=0; op<2; ++op) {1310logln("Testing GregorianCalendar " + (op==0 ? "add" : "roll"));13111312for (int field=0; field < Calendar.FIELD_COUNT; ++field) {1313if (field != Calendar.ZONE_OFFSET &&1314field != Calendar.DST_OFFSET) {1315for (int j=0; j<fieldsList.length; ++j) {1316int fields[] = fieldsList[j];1317cal.clear();1318cal.set(fields[0], fields[1], fields[2],1319fields[3], fields[4], fields[5]);1320cal.set(Calendar.MILLISECOND, fields[6]);1321for (int i = 0; i < 2*limit; i++) {1322if (op == 0) {1323cal.add(field, i < limit ? 1 : -1);1324} else {1325cal.roll(field, i < limit ? 1 : -1);1326}1327}13281329if (cal.get(Calendar.YEAR) != fields[0] ||1330cal.get(Calendar.MONTH) != fields[1] ||1331cal.get(Calendar.DATE) != fields[2] ||1332cal.get(Calendar.HOUR_OF_DAY) != fields[3] ||1333cal.get(Calendar.MINUTE) != fields[4] ||1334cal.get(Calendar.SECOND) != fields[5] ||1335cal.get(Calendar.MILLISECOND) != fields[6]) {1336errln("Field " + field +1337" (" + fieldNames[field] +1338") FAIL, expected " +1339fields[0] +1340"/" + (fields[1] + 1) +1341"/" + fields[2] +1342" " + fields[3] +1343":" + fields[4] +1344":" + fields[5] +1345"." + fields[6] +1346", got " + cal.get(Calendar.YEAR) +1347"/" + (cal.get(Calendar.MONTH) + 1) +1348"/" + cal.get(Calendar.DATE) +1349" " + cal.get(Calendar.HOUR_OF_DAY) +1350":" + cal.get(Calendar.MINUTE) +1351":" + cal.get(Calendar.SECOND) +1352"." + cal.get(Calendar.MILLISECOND));13531354cal.clear();1355cal.set(fields[0], fields[1], fields[2],1356fields[3], fields[4], fields[5]);1357cal.set(Calendar.MILLISECOND, fields[6]);1358errln(cal.get(Calendar.YEAR) +1359"/" + (cal.get(Calendar.MONTH) + 1) +1360"/" + cal.get(Calendar.DATE) +1361" " + cal.get(Calendar.HOUR_OF_DAY) +1362":" + cal.get(Calendar.MINUTE) +1363":" + cal.get(Calendar.SECOND) +1364"." + cal.get(Calendar.MILLISECOND));13651366long prev = cal.getTime().getTime();1367for (int i = 0; i < 2*limit; i++) {1368if (op == 0) {1369cal.add(field, i < limit ? 1 : -1);1370} else {1371cal.roll(field, i < limit ? 1 : -1);1372}1373long t = cal.getTime().getTime();1374long delta = t - prev;1375prev = t;1376errln((op == 0 ? "add(" : "roll(") +1377fieldNames[field] + ", " +1378(i < limit ? "+" : "-") + "1) => " +1379cal.get(Calendar.YEAR) +1380"/" + (cal.get(Calendar.MONTH) + 1) +1381"/" + cal.get(Calendar.DATE) +1382" " + cal.get(Calendar.HOUR_OF_DAY) +1383":" + cal.get(Calendar.MINUTE) +1384":" + cal.get(Calendar.SECOND) +1385"." + cal.get(Calendar.MILLISECOND) +1386" d=" + delta);1387}1388}1389}1390}1391}1392}1393}1394finally {1395Locale.setDefault(savedLocale);1396}1397}13981399public void Test4174361() {1400GregorianCalendar calendar = new GregorianCalendar(1996, 1, 29);14011402calendar.add(Calendar.MONTH, 10);1403Date date1 = calendar.getTime();1404int d1 = calendar.get(Calendar.DAY_OF_MONTH);14051406calendar = new GregorianCalendar(1996, 1, 29);1407calendar.add(Calendar.MONTH, 11);1408Date date2 = calendar.getTime();1409int d2 = calendar.get(Calendar.DAY_OF_MONTH);14101411if (d1 != d2) {1412errln("adding months to Feb 29 broken");1413}1414}14151416/**1417* Calendar does not update field values when setTimeZone is called.1418*/1419public void Test4177484() {1420TimeZone PST = TimeZone.getTimeZone("PST");1421TimeZone EST = TimeZone.getTimeZone("EST");14221423Calendar cal = Calendar.getInstance(PST, Locale.US);1424cal.clear();1425cal.set(1999, 3, 21, 15, 5, 0); // Arbitrary1426int h1 = cal.get(Calendar.HOUR_OF_DAY);1427cal.setTimeZone(EST);1428int h2 = cal.get(Calendar.HOUR_OF_DAY);1429if (h1 == h2) {1430errln("FAIL: Fields not updated after setTimeZone");1431}14321433// getTime() must NOT change when time zone is changed.1434// getTime() returns zone-independent time in ms.1435cal.clear();1436cal.setTimeZone(PST);1437cal.set(Calendar.HOUR_OF_DAY, 10);1438Date pst10 = cal.getTime();1439cal.setTimeZone(EST);1440Date est10 = cal.getTime();1441if (!pst10.equals(est10)) {1442errln("FAIL: setTimeZone changed time");1443}1444}14451446/**1447* Week of year is wrong at the start and end of the year.1448*/1449public void Test4197699() {1450GregorianCalendar cal = new GregorianCalendar();1451cal.setFirstDayOfWeek(Calendar.MONDAY);1452cal.setMinimalDaysInFirstWeek(4);1453DateFormat fmt = new SimpleDateFormat("E dd MMM yyyy 'DOY='D 'WOY='w");1454fmt.setCalendar(cal);14551456int[] DATA = {14572000, Calendar.JANUARY, 1, 52,14582001, Calendar.DECEMBER, 31, 1,1459};14601461for (int i=0; i<DATA.length; ) {1462cal.set(DATA[i++], DATA[i++], DATA[i++]);1463int expWOY = DATA[i++];1464int actWOY = cal.get(Calendar.WEEK_OF_YEAR);1465if (expWOY == actWOY) {1466logln("Ok: " + fmt.format(cal.getTime()));1467} else {1468errln("FAIL: " + fmt.format(cal.getTime())1469+ ", expected WOY=" + expWOY);1470cal.add(Calendar.DATE, -8);1471for (int j=0; j<14; ++j) {1472cal.add(Calendar.DATE, 1);1473logln(fmt.format(cal.getTime()));1474}1475}1476}1477}14781479/**1480* Calendar DAY_OF_WEEK_IN_MONTH fields->time broken. The problem1481* is in the field disambiguation code in GregorianCalendar. This1482* code is supposed to choose the most recent set of fields1483* among the following:1484*1485* MONTH + DAY_OF_MONTH1486* MONTH + WEEK_OF_MONTH + DAY_OF_WEEK1487* MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK1488* DAY_OF_YEAR1489* WEEK_OF_YEAR + DAY_OF_WEEK1490*/1491public void Test4209071() {1492Calendar cal = Calendar.getInstance(Locale.US);14931494// General field setting test1495int Y = 1995 - 1900;14961497Object[] FIELD_DATA = {1498// Add new test cases as needed.14991500// 01501new int[] {}, new Date(Y, Calendar.JANUARY, 1),1502// 11503new int[] { Calendar.MONTH, Calendar.MARCH },1504new Date(Y, Calendar.MARCH, 1),1505// 21506new int[] { Calendar.DAY_OF_WEEK, Calendar.WEDNESDAY },1507new Date(Y, Calendar.JANUARY, 4),1508// 31509new int[] { Calendar.DAY_OF_WEEK, Calendar.THURSDAY,1510Calendar.DAY_OF_MONTH, 18, },1511new Date(Y, Calendar.JANUARY, 18),1512// 41513new int[] { Calendar.DAY_OF_MONTH, 18,1514Calendar.DAY_OF_WEEK, Calendar.THURSDAY, },1515new Date(Y, Calendar.JANUARY, 18),1516// 5 (WOM -1 is in previous month)1517new int[] { Calendar.DAY_OF_MONTH, 18,1518Calendar.WEEK_OF_MONTH, -1,1519Calendar.DAY_OF_WEEK, Calendar.THURSDAY, },1520new Date(Y-1, Calendar.DECEMBER, 22),1521// 61522new int[] { Calendar.DAY_OF_MONTH, 18,1523Calendar.WEEK_OF_MONTH, 4,1524Calendar.DAY_OF_WEEK, Calendar.THURSDAY, },1525new Date(Y, Calendar.JANUARY, 26),1526// 7 (DIM -1 is in same month)1527new int[] { Calendar.DAY_OF_MONTH, 18,1528Calendar.DAY_OF_WEEK_IN_MONTH, -1,1529Calendar.DAY_OF_WEEK, Calendar.THURSDAY, },1530new Date(Y, Calendar.JANUARY, 26),1531// 81532new int[] { Calendar.WEEK_OF_YEAR, 9,1533Calendar.DAY_OF_WEEK, Calendar.WEDNESDAY, },1534new Date(Y, Calendar.MARCH, 1),1535// 91536new int[] { Calendar.MONTH, Calendar.OCTOBER,1537Calendar.DAY_OF_WEEK_IN_MONTH, 1,1538Calendar.DAY_OF_WEEK, Calendar.FRIDAY, },1539new Date(Y, Calendar.OCTOBER, 6),1540// 101541new int[] { Calendar.MONTH, Calendar.OCTOBER,1542Calendar.WEEK_OF_MONTH, 2,1543Calendar.DAY_OF_WEEK, Calendar.FRIDAY, },1544new Date(Y, Calendar.OCTOBER, 13),1545// 111546new int[] { Calendar.MONTH, Calendar.OCTOBER,1547Calendar.DAY_OF_MONTH, 15,1548Calendar.DAY_OF_YEAR, 222, },1549new Date(Y, Calendar.AUGUST, 10),1550// 121551new int[] { Calendar.DAY_OF_WEEK, Calendar.THURSDAY,1552Calendar.MONTH, Calendar.DECEMBER, },1553new Date(Y, Calendar.DECEMBER, 7),1554};15551556for (int i=0; i<FIELD_DATA.length; i+=2) {1557int[] fields = (int[]) FIELD_DATA[i];1558Date exp = (Date) FIELD_DATA[i+1];15591560cal.clear();1561cal.set(Calendar.YEAR, Y + 1900);1562for (int j=0; j<fields.length; j+=2) {1563cal.set(fields[j], fields[j+1]);1564}15651566Date act = cal.getTime();1567if (!act.equals(exp)) {1568errln("FAIL: Test " + (i/2) + " got " + act +1569", want " + exp +1570" (see test/java/util/Calendar/CalendarRegression.java");1571}1572}15731574// Test specific failure reported in bug1575Object[] DATA = {1576new Integer(1), new Date(1997-1900, Calendar.JANUARY, 5),1577new Integer(4), new Date(1997-1900, Calendar.JANUARY, 26),1578new Integer(8), new Date(1997-1900, Calendar.FEBRUARY, 23),1579new Integer(-1), new Date(1997-1900, Calendar.JANUARY, 26),1580new Integer(-4), new Date(1997-1900, Calendar.JANUARY, 5),1581new Integer(-8), new Date(1996-1900, Calendar.DECEMBER, 8),1582};1583for (int i=0; i<DATA.length; i+=2) {1584cal.clear();1585cal.set(Calendar.DAY_OF_WEEK_IN_MONTH,1586((Number) DATA[i]).intValue());1587cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);1588cal.set(Calendar.MONTH, Calendar.JANUARY);1589cal.set(Calendar.YEAR, 1997);1590Date actual = cal.getTime();1591if (!actual.equals(DATA[i+1])) {1592errln("FAIL: Sunday " + DATA[i] +1593" of Jan 1997 -> " + actual +1594", want " + DATA[i+1]);1595}1596}1597}15981599public void Test4288792() throws Exception1600{1601TimeZone savedTZ = TimeZone.getDefault();1602TimeZone.setDefault(TimeZone.getTimeZone("GMT"));1603GregorianCalendar cal = new GregorianCalendar();1604try {1605for (int i = 1900; i < 2100; i++) {1606for (int j1 = 1; j1 <= 7; j1++) {1607// Loop for MinimalDaysInFirstWeek: 1..71608for (int j = Calendar.SUNDAY; j <= Calendar.SATURDAY; j++) {1609// Loop for FirstDayOfWeek: SUNDAY..SATURDAY1610cal.clear();1611cal.setMinimalDaysInFirstWeek(j1);1612cal.setFirstDayOfWeek(j);1613cal.set(Calendar.YEAR, i);1614int maxWeek = cal.getActualMaximum(Calendar.WEEK_OF_YEAR);1615cal.set(Calendar.WEEK_OF_YEAR, maxWeek);1616cal.set(Calendar.DAY_OF_WEEK, j);16171618for (int k = 1; k < 7; k++) {1619cal.add(Calendar.DATE, 1);1620int WOY = cal.get(Calendar.WEEK_OF_YEAR);1621if (WOY != maxWeek) {1622errln(cal.getTime() + ",got=" + WOY1623+ ",expected=" + maxWeek1624+ ",min=" + j1 + ",first=" + j);1625}1626}16271628cal.add(Calendar.DATE, 1);1629int WOY = cal.get(Calendar.WEEK_OF_YEAR);1630if (WOY != 1) {1631errln(cal.getTime() + ",got=" + WOY1632+ ",expected=1,min=" + j1 + ",first" + j);1633}1634}1635}1636}1637}1638finally {1639TimeZone.setDefault(savedTZ);1640}1641}16421643public void Test4328747() throws Exception {1644Calendar c = (Calendar)Calendar.getInstance(Locale.US);1645c.clear();1646c.set(1966,0,1); // 1 jan 196616471648// serialize1649ByteArrayOutputStream out = new ByteArrayOutputStream();1650ObjectOutputStream s = new ObjectOutputStream(out);1651s.writeObject(c);1652s.flush();16531654// deserialize1655ObjectInputStream t = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray()));1656Calendar result = (Calendar)t.readObject();16571658// let recalculate fields with the same UTC time1659result.setTime(result.getTime());1660// Bug gives 1965 11 191661if ((result.get(c.YEAR) != 1966) || (result.get(c.MONTH) != 0)1662|| (result.get(c.DATE) != 1)) {1663errln("deserialized Calendar returned wrong date field(s): "1664+ result.get(c.YEAR) + "/" + result.get(c.MONTH) + "/" + result.get(c.DATE)1665+ ", expected 1966/0/1");1666}1667}16681669/**1670* Test whether Calendar can be serialized/deserialized correctly1671* even if invalid/customized TimeZone is used.1672*/1673public void Test4413980() {1674TimeZone savedTimeZone = TimeZone.getDefault();1675try {1676boolean pass = true;1677String[] IDs = new String[] {"Undefined", "PST", "US/Pacific",1678"GMT+3:00", "GMT-01:30"};1679for (int i = 0; i < IDs.length; i++) {1680TimeZone tz = TimeZone.getTimeZone(IDs[i]);1681TimeZone.setDefault(tz);16821683Calendar c = (Calendar)Calendar.getInstance();16841685// serialize1686ByteArrayOutputStream out = new ByteArrayOutputStream();1687ObjectOutputStream s = new ObjectOutputStream(out);1688s.writeObject(c);1689s.flush();16901691// deserialize1692ObjectInputStream t = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray()));16931694if (!c.equals(t.readObject())) {1695pass = false;1696logln("Calendar instance which uses TimeZone <" +1697IDs[i] + "> is incorrectly serialized/deserialized.");1698} else {1699logln("Calendar instance which uses TimeZone <" +1700IDs[i] + "> is correctly serialized/deserialized.");1701}1702}1703if (!pass) {1704errln("Fail: Calendar serialization/equality bug");1705}1706}1707catch (IOException e) {1708errln("Fail: " + e);1709e.printStackTrace();1710}1711catch (ClassNotFoundException e) {1712errln("Fail: " + e);1713e.printStackTrace();1714}1715finally {1716TimeZone.setDefault(savedTimeZone);1717}1718}17191720/**1721* 4546637: Incorrect WEEK_OF_MONTH after changing First Day Of Week1722*/1723public void Test4546637() {1724GregorianCalendar day = new GregorianCalendar (2001, Calendar.NOVEMBER, 04);1725day.setMinimalDaysInFirstWeek(1);1726int wom = day.get(Calendar.WEEK_OF_MONTH);17271728day.setFirstDayOfWeek(Calendar.MONDAY);1729if (day.get(Calendar.WEEK_OF_MONTH) != 1) {1730errln("Fail: 2001/11/4 must be the first week of the month.");1731}1732}17331734/**1735* 4623997: GregorianCalendar returns bad WEEK_OF_YEAR1736*/1737public void Test4623997() {1738GregorianCalendar cal = new GregorianCalendar(2000, GregorianCalendar.JANUARY, 1);17391740int dow = cal.get(GregorianCalendar.DAY_OF_WEEK);17411742cal.setFirstDayOfWeek(GregorianCalendar.MONDAY);1743cal.setMinimalDaysInFirstWeek(4);17441745if (cal.get(GregorianCalendar.WEEK_OF_YEAR) != 52) {1746errln("Fail: 2000/1/1 must be the 52nd week of the year.");1747}1748}17491750/**1751* 4685354: Handling of Calendar fields setting state is broken1752*1753* <p>Need to use SimpleDateFormat to test because a call to1754* get(int) changes internal states of a Calendar.1755*/1756public void Test4685354() {1757if (Locale.getDefault().equals(new Locale("hi", "IN"))) {1758return;1759}17601761Calendar calendar = Calendar.getInstance(Locale.US);1762DateFormat df = new SimpleDateFormat("yyyy/MM/dd", Locale.US);1763String expected = "1999/12/31";1764Date t;1765String s;17661767try {1768calendar.setTime(df.parse(expected));1769} catch (Exception e) {1770throw new RuntimeException("Unexpected parse exception", e);1771}17721773t = calendar.getTime();1774calendar.set(Calendar.DAY_OF_MONTH, 33);1775t = calendar.getTime();1776calendar.set(Calendar.DAY_OF_MONTH, 0);1777s = df.format(calendar.getTime());1778if (!expected.equals(s)) {1779errln("DAY_OF_MONTH w/o ZONE_OFFSET: expected: " + expected + ", got: " + s);1780}17811782// The same thing must work with ZONE_OFFSET set1783try {1784calendar.setTime(df.parse(expected));1785} catch (Exception e) {1786throw new RuntimeException("Unexpected parse exception", e);1787}1788t = calendar.getTime();1789calendar.set(calendar.ZONE_OFFSET, calendar.get(calendar.ZONE_OFFSET));1790calendar.set(Calendar.DAY_OF_MONTH, 33);1791t = calendar.getTime();1792calendar.set(Calendar.DAY_OF_MONTH, 0);1793s = df.format(calendar.getTime());1794if (!expected.equals(s)) {1795errln("DAY_OF_MONTH: expected: " + expected + ", got: " + s);1796}17971798expected = "1999/12/24"; // 0th week of 20001799calendar.clear();1800Date initialDate = null;1801try {1802initialDate = df.parse(expected);1803calendar.setTime(initialDate);1804} catch (Exception e) {1805throw new RuntimeException("Unexpected parse exception", e);1806}1807t = calendar.getTime();1808calendar.set(calendar.ZONE_OFFSET, calendar.get(calendar.ZONE_OFFSET));1809// jump to the next year1810calendar.set(Calendar.WEEK_OF_YEAR, 100);1811t = calendar.getTime();1812calendar.set(Calendar.WEEK_OF_YEAR, 0);1813s = df.format(calendar.getTime());1814if (!expected.equals(s)) {1815errln("WEEK_OF_YEAR: expected: " + expected + ", got: " + s);1816}1817// change the state back1818calendar.clear();1819calendar.setTime(initialDate);1820calendar.set(calendar.ZONE_OFFSET, calendar.get(calendar.ZONE_OFFSET));1821// jump to next month1822calendar.set(Calendar.WEEK_OF_MONTH, 7);1823t = calendar.getTime();1824calendar.set(Calendar.WEEK_OF_MONTH, 0);1825s = df.format(calendar.getTime());1826if (!expected.equals(s)) {1827errln("WEEK_OF_MONTH: expected: " + expected + ", got: " + s);1828}18291830// Make sure the time fields work correctly.1831calendar.clear();1832df = new SimpleDateFormat("HH:mm:ss");1833TimeZone tz = TimeZone.getTimeZone("GMT");1834df.setTimeZone(tz);1835calendar.setTimeZone(tz);1836expected = "22:59:59";1837try {1838calendar.setTime(df.parse(expected));1839} catch (Exception e) {1840throw new RuntimeException("Unexpected parse exception", e);1841}1842t = calendar.getTime();1843// time should be 22:59:59.1844calendar.set(Calendar.MINUTE, 61);1845// time should be 23:01:59.1846t = calendar.getTime();1847calendar.set(Calendar.MINUTE, -1);1848// time should be back to 22:59:59.1849s = df.format(calendar.getTime());1850if (!expected.equals(s)) {1851errln("MINUTE: expected: " + expected + ", got: " + s);1852}1853}18541855/**1856* 4655637: Calendar.set() for DAY_OF_WEEK does not return the right value1857*1858* <p>Need to use SimpleDateFormat to test because a call to1859* get(int) changes internal states of a Calendar.1860*/1861public void Test4655637() {1862// Skip this test case if it's Thai locale1863if (Locale.getDefault().equals(new Locale("th", "TH"))) {1864return;1865}18661867Calendar cal = Calendar.getInstance();1868cal.setTime(new Date(1029814211523L));1869cal.set(Calendar.YEAR, 2001);1870Date t = cal.getTime();1871cal.set(Calendar.MONTH, Calendar.JANUARY);1872t = cal.getTime();18731874cal.set(Calendar.DAY_OF_MONTH, 8);1875t = cal.getTime();18761877cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);1878DateFormat df = new SimpleDateFormat("yyyy/MM/dd", Locale.US);1879String expected = "2001/01/08";1880String s = df.format(cal.getTime());1881if (!expected.equals(s)) {1882errln("expected: " + expected + ", got: " + s);1883}1884}18851886/**1887* 4683492: Invalid value for MONTH in GregorianCalendar causes exception in getTime().1888*1889* <p>Need to use SimpleDateFormat to test because a call to1890* get(int) changes internal states of a Calendar.1891*1892* <p>This test case throws ArrayIndexOutOfBoundsException without the fix.1893*/1894public void Test4683492() {1895Calendar cal = new GregorianCalendar(2002, 3, 29, 10, 0, 0);1896cal.set(Calendar.DAY_OF_WEEK, Calendar.FRIDAY);1897cal.set(Calendar.DAY_OF_WEEK_IN_MONTH, -1);1898cal.set(Calendar.MONTH, 12);1899DateFormat df = new SimpleDateFormat("yyyy/MM/dd", Locale.US);1900String expected = "2003/01/31";1901String s = df.format(cal.getTime());1902if (!expected.equals(s)) {1903errln("expected: " + expected + ", got: " + s);1904}1905}19061907/**1908* 4080631: Calendar.hashCode is amazingly bad1909*/1910public void Test4080631() {1911Calendar cal = Calendar.getInstance();1912int h1 = cal.hashCode();1913cal.add(cal.SECOND, +1);1914int h2 = cal.hashCode();1915Calendar cal2 = (Calendar) cal.clone();1916cal.add(cal.MILLISECOND, +1);1917int h3 = cal.hashCode();1918logln("hash code: h1="+h1+", h2="+h2+", h3="+h3);1919if (h1 == h2 || h1 == h3 || h2 == h3) {1920errln("hash code is poor: hashCode="+h1);1921}1922h2 = cal2.hashCode();1923cal.add(cal.MILLISECOND, -1);1924int h4 = cal.hashCode();1925logln("hash code: h2="+h2+", h4="+h4);1926if (cal.equals(cal2) && h2 != h4) {1927errln("broken hash code: h2="+h2+", h4="+h4);1928}1929int x = cal.getFirstDayOfWeek() + 3;1930if (x > cal.SATURDAY) {1931x -= 7;1932}1933cal.setFirstDayOfWeek(x);1934int h5 = cal.hashCode();1935logln("hash code: h4="+h4+", h5="+h5);1936if (h4 == h5) {1937errln("has code is poor with first day of week param: hashCode="+h4);1938}1939}19401941/**1942* 4125161: RFE: GregorianCalendar needs more era names (BCE and CE)1943*/1944/*1945public void Test4125161() throws Exception {1946Class gc = GregorianCalendar.class;1947Field f;1948int mod;1949f = gc.getDeclaredField("BCE");1950mod = f.getModifiers();1951if (!Modifier.isStatic(mod) || !Modifier.isFinal(mod)) {1952errln("BCE: wrong modifiers: " + mod);1953}1954f = gc.getDeclaredField("CE");1955mod = f.getModifiers();1956if (!Modifier.isStatic(mod) || !Modifier.isFinal(mod)) {1957errln("CE: wrong modifiers: " + mod);1958}1959if (GregorianCalendar.BCE != GregorianCalendar.BC1960|| GregorianCalendar.CE != GregorianCalendar.AD) {1961errln("Wrong BCE and/or CE values");1962}1963}1964*/19651966/**1967* 4167995: GregorianCalendar.setGregorianChange() not to spec1968*/1969public void Test4167995() {1970Koyomi gc = new Koyomi(TimeZone.getTimeZone("GMT"));1971logln("Hybrid: min date");1972gc.setTime(new Date(Long.MIN_VALUE));1973if (!gc.checkDate(292269055, gc.DECEMBER, 2, gc.SUNDAY)1974|| !gc.checkFieldValue(gc.ERA, gc.BC)) {1975errln(gc.getMessage());1976}1977logln("Hybrid: max date");1978gc.setTime(new Date(Long.MAX_VALUE));1979if (!gc.checkDate(292278994, gc.AUGUST, 17, gc.SUNDAY)1980|| !gc.checkFieldValue(gc.ERA, gc.AD)) {1981errln(gc.getMessage());1982}19831984gc.setGregorianChange(new Date(Long.MIN_VALUE));1985logln("Gregorian: min date");1986gc.setTime(new Date(Long.MIN_VALUE));1987if (!gc.checkDate(292275056, gc.MAY, 16, gc.SUNDAY)1988|| !gc.checkFieldValue(gc.ERA, gc.BC)) {1989errln(gc.getMessage());1990}1991logln("Gregorian: max date");1992gc.setTime(new Date(Long.MAX_VALUE));1993if (!gc.checkDate(292278994, gc.AUGUST, 17, gc.SUNDAY)1994|| !gc.checkFieldValue(gc.ERA, gc.AD)) {1995errln(gc.getMessage());1996}19971998gc.setGregorianChange(new Date(Long.MAX_VALUE));1999logln("Julian: min date");2000gc.setTime(new Date(Long.MIN_VALUE));2001if (!gc.checkDate(292269055, gc.DECEMBER, 2, gc.SUNDAY)2002|| !gc.checkFieldValue(gc.ERA, gc.BC)) {2003errln(gc.getMessage());2004}2005logln("Julian: max date");2006gc.setTime(new Date(Long.MAX_VALUE));2007if (!gc.checkDate(292272993, gc.JANUARY, 4, gc.SUNDAY)2008|| !gc.checkFieldValue(gc.ERA, gc.AD)) {2009errln(gc.getMessage());2010}2011}20122013/**2014* 4340146: Calendar.equals modifies state2015*/2016public void Test4340146() {2017Koyomi cal = new Koyomi();2018cal.clear();2019cal.set(2003, cal.OCTOBER, 32);2020cal.equals(new Koyomi());2021if (!cal.checkInternalDate(2003, cal.OCTOBER, 32)) {2022errln(cal.getMessage());2023}2024new Koyomi().equals(cal);2025if (!cal.checkInternalDate(2003, cal.OCTOBER, 32)) {2026errln(cal.getMessage());2027}2028}20292030/**2031* 4639407: GregorianCalendar doesn't work in non-lenient due to timezone bounds checking2032*/2033public void Test4639407() {2034// The following operations in non-lenient mode shouldn't2035// throw IllegalArgumentException.2036Koyomi cal = new Koyomi(TimeZone.getTimeZone("Pacific/Kiritimati"));2037cal.setLenient(false);2038cal.set(2003, cal.OCTOBER, 10);2039cal.getTime();2040cal.setTimeZone(TimeZone.getTimeZone("Pacific/Tongatapu"));2041cal.set(2003, cal.OCTOBER, 10);2042cal.getTime();2043}20442045/**2046* 4652815: rolling week-of-year back hundreds of weeks changes year2047*/2048public void Test4652815() {2049Koyomi cal = new Koyomi(Locale.US);2050testRoll(cal, 2003, cal.SEPTEMBER, 29);2051testRoll(cal, 2003, cal.DECEMBER, 24);2052testRoll(cal, 1582, cal.DECEMBER, 19);2053testRoll(cal, 1582, cal.DECEMBER, 20);2054}20552056private void testRoll(Koyomi cal, int year, int month, int dayOfMonth) {2057cal.clear();2058cal.set(year, month, dayOfMonth);2059cal.getTime(); // normalize fields2060logln("Roll backwards from " + cal.toDateString());2061for (int i = 0; i < 1000; i++) {2062cal.roll(cal.WEEK_OF_YEAR, -i);2063if (!cal.checkFieldValue(cal.YEAR, year)) {2064errln(cal.getMessage());2065}2066}2067logln("Roll forewards from " + cal.toDateString());2068for (int i = 0; i < 1000; i++) {2069cal.roll(cal.WEEK_OF_YEAR, +i);2070if (!cal.checkFieldValue(cal.YEAR, year)) {2071errln(cal.getMessage());2072}2073}2074}20752076/**2077* 4652830: GregorianCalendar roll behaves unexpectedly for dates in BC era2078*/2079public void Test4652830() {2080Koyomi cal = new Koyomi(Locale.US);2081cal.clear();2082logln("BCE 9-2-28 (leap year) roll DAY_OF_MONTH++ twice");2083cal.set(cal.ERA, cal.BC);2084cal.set(9, cal.FEBRUARY, 28);2085if (cal.getActualMaximum(cal.DAY_OF_YEAR) != 366) {2086errln(" wrong actual max of DAY_OF_YEAR: got "2087+ cal.getActualMaximum(cal.DAY_OF_YEAR) + " expected " + 366);2088}2089cal.roll(cal.DAY_OF_MONTH, +1);2090if (!cal.checkFieldValue(cal.ERA, cal.BC)2091|| !cal.checkDate(9, cal.FEBRUARY, 29)) {2092errln(cal.getMessage());2093}2094cal.roll(cal.DAY_OF_MONTH, +1);2095if (!cal.checkFieldValue(cal.ERA, cal.BC)2096|| !cal.checkDate(9, cal.FEBRUARY, 1)) {2097errln(cal.getMessage());2098}2099}21002101/**2102* 4740554: GregorianCalendar.getActualMaximum is inconsistent with normalization2103*/2104public void Test4740554() {2105logln("1999/(Feb+12)/1 should be normalized to 2000/Feb/1 for getActualMaximum");2106Koyomi cal = new Koyomi(Locale.US);2107cal.clear();2108cal.set(1999, cal.FEBRUARY + 12, 1);2109if (!cal.checkActualMaximum(cal.DAY_OF_YEAR, 366)) {2110errln(cal.getMessage());2111}2112if (!cal.checkActualMaximum(cal.DAY_OF_MONTH, 29)) {2113errln(cal.getMessage());2114}2115}21162117/**2118* 4936355: GregorianCalendar causes overflow/underflow with time of day calculation2119*/2120public void Test4936355() {2121Koyomi cal = new Koyomi(TimeZone.getTimeZone("GMT"));2122cal.clear();2123cal.set(1970, cal.JANUARY, 1);2124checkTimeCalculation(cal, cal.HOUR_OF_DAY, Integer.MAX_VALUE,2125(long)Integer.MAX_VALUE * 60 * 60 * 1000);21262127cal.clear();2128cal.set(1970, cal.JANUARY, 1);2129checkTimeCalculation(cal, cal.HOUR, Integer.MAX_VALUE,2130(long)Integer.MAX_VALUE * 60 * 60 * 1000);21312132cal.clear();2133cal.set(1970, cal.JANUARY, 1);2134checkTimeCalculation(cal, cal.MINUTE, Integer.MAX_VALUE,2135(long)Integer.MAX_VALUE * 60 * 1000);21362137cal.clear();2138// Make sure to use Gregorian dates (before and after the2139// set() call) for testing2140cal.set(250000, cal.JANUARY, 1);2141checkTimeCalculation(cal, cal.HOUR_OF_DAY, Integer.MIN_VALUE,2142(long)Integer.MIN_VALUE * 60 * 60 * 1000);21432144cal.clear();2145cal.set(250000, cal.JANUARY, 1);2146checkTimeCalculation(cal, cal.HOUR, Integer.MIN_VALUE,2147(long)Integer.MIN_VALUE * 60 * 60 * 1000);21482149cal.clear();2150cal.set(250000, cal.JANUARY, 1);2151checkTimeCalculation(cal, cal.MINUTE, Integer.MIN_VALUE,2152(long)Integer.MIN_VALUE * 60 * 1000);2153}21542155private void checkTimeCalculation(Koyomi cal, int field, int value, long expectedDelta) {2156long time = cal.getTimeInMillis();2157cal.set(field, value);2158long time2 = cal.getTimeInMillis();2159if ((time + expectedDelta) != time2) {2160String s = value == Integer.MAX_VALUE ? "Integer.MAX_VALUE" : "Integer.MIN_VALUE";2161errln("set(" + Koyomi.getFieldName(field) + ", " + s + ") failed." + " got " + time22162+ ", expected " + (time+expectedDelta));2163}2164}21652166/**2167* 4722650: Calendar.equals can throw an exception in non-lenient2168* (piggy-back tests for compareTo() which is new in 1.5)2169*/2170public void Test4722650() {2171Calendar cal1 = new GregorianCalendar();2172cal1.clear();2173Calendar cal2 = new GregorianCalendar();2174cal2.clear();2175cal2.setLenient(false);21762177cal1.set(2003, Calendar.OCTOBER, 31);2178cal2.set(2003, Calendar.OCTOBER, 31);2179try {2180if (cal1.equals(cal2)) {2181errln("lenient and non-lenient shouldn't be equal. (2003/10/31)");2182}2183if (cal1.compareTo(cal2) != 0) {2184errln("cal1 and cal2 should represent the same time. (2003/10/31)");2185}2186} catch (IllegalArgumentException e) {2187errln("equals threw IllegalArugumentException with non-lenient");2188}21892190cal1.set(2003, Calendar.OCTOBER, 32);2191cal2.set(2003, Calendar.OCTOBER, 32);2192try {2193if (cal1.equals(cal2)) {2194errln("lenient and non-lenient shouldn't be equal. (2003/10/32)");2195}2196if (cal1.compareTo(cal2) != 0) {2197errln("cal1 and cal2 should represent the same time. (2003/10/32)");2198}2199} catch (IllegalArgumentException e) {2200errln("equals threw IllegalArugumentException with non-lenient");2201}22022203cal1 = Calendar.getInstance(new Locale("th", "TH"));2204cal1.setTimeInMillis(0L);2205cal2 = Calendar.getInstance(Locale.US);2206cal2.setTimeInMillis(0L);2207if (cal1.equals(cal2)) {2208errln("Buddhist.equals(Gregorian) shouldn't be true. (millis=0)");2209}2210if (cal1.compareTo(cal2) != 0) {2211errln("cal1 (Buddhist) and cal2 (Gregorian) should represent the same time. (millis=0)");2212}2213}22142215/**2216* 4738710: API: Calendar comparison methods should be improved2217*/2218public void Test4738710() {2219Calendar cal0 = new GregorianCalendar(2003, Calendar.SEPTEMBER, 30);2220Comparable<Calendar> cal1 = new GregorianCalendar(2003, Calendar.OCTOBER, 1);2221Calendar cal2 = new GregorianCalendar(2003, Calendar.OCTOBER, 2);2222if (!(cal1.compareTo(cal0) > 0)) {2223errln("!(cal1 > cal0)");2224}2225if (!(cal1.compareTo(cal2) < 0)) {2226errln("!(cal1 < cal2)");2227}2228if (cal1.compareTo(new GregorianCalendar(2003, Calendar.OCTOBER, 1)) != 0) {2229errln("cal1 != new GregorianCalendar(2003, Calendar.OCTOBER, 1)");2230}22312232if (cal0.after(cal2)) {2233errln("cal0 shouldn't be after cal2");2234}2235if (cal2.before(cal0)) {2236errln("cal2 shouldn't be before cal0");2237}22382239if (cal0.after(new Integer(0))) {2240errln("cal0.after() returned true with an Integer.");2241}2242if (cal0.before(new Integer(0))) {2243errln("cal0.before() returned true with an Integer.");2244}2245if (cal0.after(null)) {2246errln("cal0.after() returned true with null.");2247}2248if (cal0.before(null)) {2249errln("cal0.before() returned true with null.");2250}2251}22522253/**2254* 4633646: Setting WEEK_OF_MONTH to 1 results in incorrect date2255*/2256public void Test4633646() {2257Koyomi cal = new Koyomi(Locale.US);2258cal.setTime(new Date(2002-1900, 1-1, 28));2259sub4633646(cal);22602261cal.setLenient(false);2262cal.setTime(new Date(2002-1900, 1-1, 28));2263sub4633646(cal);22642265cal = new Koyomi(Locale.US);2266cal.clear();2267cal.set(2002, cal.JANUARY, 28);2268sub4633646(cal);22692270cal.clear();2271cal.setLenient(false);2272cal.set(2002, cal.JANUARY, 28);2273sub4633646(cal);2274}22752276void sub4633646(Koyomi cal) {2277cal.getTime();2278cal.set(cal.WEEK_OF_MONTH, 1);2279if (cal.isLenient()) {2280if (!cal.checkDate(2001, cal.DECEMBER, 31)) {2281errln(cal.getMessage());2282}2283if (!cal.checkFieldValue(cal.WEEK_OF_MONTH, 6)) {2284errln(cal.getMessage());2285}2286} else {2287try {2288Date d = cal.getTime();2289errln("didn't throw IllegalArgumentException in non-lenient");2290} catch (IllegalArgumentException e) {2291}2292}2293}22942295/**2296* 4846659: Calendar: Both set() and roll() don't work for AM_PM time field2297* (Partially fixed only roll as of 1.5)2298*/2299public void Test4846659() {2300Koyomi cal = new Koyomi();2301cal.clear();2302cal.set(2003, cal.OCTOBER, 31, 10, 30, 30);2303cal.getTime();2304// Test roll()2305cal.roll(cal.AM_PM, +1); // should turn to PM2306if (!cal.checkFieldValue(cal.HOUR_OF_DAY, 10+12)) {2307errln("roll: AM_PM didn't change to PM");2308}23092310cal.clear();2311cal.set(2003, cal.OCTOBER, 31, 10, 30, 30);2312cal.getTime();2313// Test set()2314cal.set(cal.AM_PM, cal.PM); // should turn to PM2315if (!cal.checkFieldValue(cal.HOUR_OF_DAY, 10+12)) {2316errln("set: AM_PM didn't change to PM");2317}23182319cal.clear();2320cal.set(2003, cal.OCTOBER, 31, 10, 30, 30);2321cal.getTime();2322cal.set(cal.AM_PM, cal.PM);2323cal.set(cal.HOUR, 9);2324if (!cal.checkFieldValue(cal.HOUR_OF_DAY, 9+12)) {2325errln("set: both AM_PM and HOUT didn't change to PM");2326}2327}23282329/**2330* 4822110: GregorianCalendar.get() returns an incorrect date after setFirstDayOfWeek()2331*/2332public void Test4822110() {2333Koyomi cal = new Koyomi(Locale.US);2334// June 20032335// S M Tu W Th F S2336// 1 2 3 4 5 6 72337// 8 9 10 11 12 13 142338// 15 16 17 18 19 20 212339// 22 23 24 25 26 27 282340// 29 302341cal.clear();2342// 6/1 to 6/7 should be the 1st week of June.2343cal.set(2003, cal.JUNE, 2);2344cal.getTime(); // Let cal calculate time.2345cal.setFirstDayOfWeek(cal.MONDAY);2346// Now 6/2 to 6/8 should be the 2nd week of June. Sunday of2347// that week is 6/8.2348logln("1: " +cal.get(cal.WEEK_OF_MONTH)+", "+cal.get(cal.DAY_OF_MONTH));2349cal.set(cal.DAY_OF_WEEK, cal.SUNDAY);2350logln("1st Sunday of June 2003 with FirstDayOfWeek=MONDAY");2351if (!cal.checkDate(2003, cal.JUNE, 8)) {2352errln(cal.getMessage());2353}2354}23552356/**2357* 4973919: Inconsistent GregorianCalendar hashCode before and after serialization2358*/2359public void Test4966499() throws Exception {2360GregorianCalendar date1 = new GregorianCalendar(2004, Calendar.JANUARY, 7);23612362// Serialize date12363ByteArrayOutputStream baos = new ByteArrayOutputStream();2364ObjectOutputStream oos = new ObjectOutputStream(baos);2365oos.writeObject(date1);23662367byte[] buffer = baos.toByteArray();23682369// Deserialize it2370ByteArrayInputStream bais = new ByteArrayInputStream(buffer);2371ObjectInputStream ois = new ObjectInputStream(bais);2372GregorianCalendar date2 = (GregorianCalendar)ois.readObject();23732374if (!date1.equals(date2)) {2375errln("date1.equals(date2) != true");2376}2377if (date1.hashCode() != date2.hashCode()) {2378errln("inconsistent hashCode() value (before=0x"2379+Integer.toHexString(date1.hashCode())+2380", after=0x"+Integer.toHexString(date2.hashCode())+")");2381}2382}23832384/**2385* 4980088: GregorianCalendar.getActualMaximum doesn't throw exception2386*/2387public void Test4980088() {2388GregorianCalendar cal = new GregorianCalendar();2389try {2390int x = cal.getMaximum(100);2391errln("getMaximum(100) didn't throw an exception.");2392} catch (IndexOutOfBoundsException e) {2393logln("getMaximum: " + e.getClass().getName() + ": " + e.getMessage());2394}23952396try {2397int x = cal.getLeastMaximum(100);2398errln("getLeastMaximum(100) didn't throw an exception.");2399} catch (IndexOutOfBoundsException e) {2400logln("getLeastMaximum: " + e.getClass().getName() + ": " + e.getMessage());2401}24022403try {2404int x = cal.getActualMaximum(100);2405errln("getActualMaximum(100) didn't throw an exception.");2406} catch (IndexOutOfBoundsException e) {2407logln("getActualMaximum: " + e.getClass().getName() + ": " + e.getMessage());2408}24092410try {2411int x = cal.getMinimum(100);2412errln("getMinimum(100) didn't throw an exception.");2413} catch (IndexOutOfBoundsException e) {2414logln("getMinimum: " + e.getClass().getName() + ": " + e.getMessage());2415}24162417try {2418int x = cal.getGreatestMinimum(100);2419errln("getGreatestMinimum(100) didn't throw an exception.");2420} catch (IndexOutOfBoundsException e) {2421logln("getGreatestMinimum: " + e.getClass().getName() + ": " + e.getMessage());2422}24232424try {2425int x = cal.getActualMinimum(100);2426errln("getActualMinimum(100) didn't throw an exception.");2427} catch (IndexOutOfBoundsException e) {2428logln("getActualMinimum: " + e.getClass().getName() + ": " + e.getMessage());2429}2430}24312432/**2433* 4965624: GregorianCalendar.isLeapYear(1000) returns incorrect value2434*/2435public void Test4965624() {2436// 5013094: This test case needs to use "GMT" to specify2437// Gregorian cutover dates.2438TimeZone savedZone = TimeZone.getDefault();2439TimeZone.setDefault(TimeZone.getTimeZone("GMT"));2440try {2441Map<Date, Boolean> data = new HashMap<Date, Boolean>();2442data.put(getGregorianDate(999, Calendar.OCTOBER, 1), Boolean.FALSE);2443data.put(getGregorianDate(1000, Calendar.JANUARY, 1), Boolean.FALSE);2444data.put(getGregorianDate(1000, Calendar.FEBRUARY, 1), Boolean.FALSE);2445data.put(getGregorianDate(1000, Calendar.FEBRUARY, 28), Boolean.FALSE);2446data.put(getGregorianDate(1000, Calendar.MARCH, 1), Boolean.TRUE);2447data.put(getGregorianDate(1001, Calendar.JANUARY, 1), Boolean.TRUE);2448data.put(getGregorianDate(1001, Calendar.JANUARY, 6), Boolean.TRUE);2449data.put(getGregorianDate(1001, Calendar.MARCH, 1), Boolean.TRUE);24502451Iterator<Date> itr = data.keySet().iterator();2452while (itr.hasNext()) {2453Date d = itr.next();2454boolean expected = data.get(d).booleanValue();2455GregorianCalendar cal = new GregorianCalendar();2456cal.setGregorianChange(d);2457if (cal.isLeapYear(1000) != expected) {2458errln("isLeapYear(1000) returned " + cal.isLeapYear(1000) +2459" with cutover date (Julian) " + d);2460}2461}2462}2463finally {2464TimeZone.setDefault(savedZone);2465}2466}24672468// Note that we can't use Date to produce Gregorian calendar dates2469// before the default cutover date.2470static Date getGregorianDate(int year, int month, int dayOfMonth) {2471GregorianCalendar g = new GregorianCalendar();2472// Make g a pure Gregorian calendar2473g.setGregorianChange(new Date(Long.MIN_VALUE));2474g.clear();2475g.set(year, month, dayOfMonth);2476return g.getTime();2477}24782479/**2480* 5006864: Define the minimum value of DAY_OF_WEEK_IN_MONTH as 12481*/2482public void Test5006864() {2483GregorianCalendar cal = new GregorianCalendar();2484int min = cal.getMinimum(cal.DAY_OF_WEEK_IN_MONTH);2485if (min != 1) {2486errln("GregorianCalendar.getMinimum(DAY_OF_WEEK_IN_MONTH) returned "2487+ min + ", expected 1.");2488}2489min = cal.getGreatestMinimum(cal.DAY_OF_WEEK_IN_MONTH);2490if (min != 1) {2491errln("GregorianCalendar.getGreatestMinimum(DAY_OF_WEEK_IN_MONTH) returned "2492+ min + ", expected 1.");2493}2494}2495}249624972498