< prev index next >

test/jdk/java/util/TimeZone/TransitionTest.java

Print this page

  1 /*
  2  * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 
 24 /*
 25  * @test
 26  * @bug 4278609 4761696
 27  * @library /java/text/testlib
 28  * @summary Make sure to handle DST transition ending at 0:00 January 1.

 29  */
 30 
 31 import java.text.SimpleDateFormat;
 32 import java.util.Calendar;
 33 import java.util.Date;
 34 import java.util.GregorianCalendar;
 35 import java.util.Locale;
 36 import java.util.SimpleTimeZone;
 37 import java.util.TimeZone;
 38 
 39 public class TransitionTest extends IntlTest {
 40 
 41     public static void main(String[] args) throws Exception {
 42         new TransitionTest().run(args);
 43     }
 44 

 45     public void Test4278609() {
 46         SimpleTimeZone tz = new SimpleTimeZone(0, "MyTimeZone",
 47                                /* DST start day: August, 1, 0:00 */
 48                                Calendar.AUGUST, 1, 0, 0,
 49                                /* DST end day: January, 1, 0:00 (wall-clock)*/
 50                                Calendar.JANUARY, 1, 0, 0,
 51                                60 * 60 * 1000);
 52 
 53         Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
 54 
 55         // setting a date using GMT zone just after the end rule of tz zone
 56         cal.clear();
 57         cal.set(Calendar.ERA, GregorianCalendar.AD);
 58         cal.set(1998, Calendar.DECEMBER, 31, 23, 01, 00);
 59 
 60         Date date = cal.getTime();
 61 
 62         int millis = cal.get(Calendar.HOUR_OF_DAY) * 3600000
 63                      + cal.get(Calendar.MINUTE) * 60000
 64                      + cal.get(Calendar.SECOND) * 1000
 65                      + cal.get(Calendar.MILLISECOND);
 66         /* we must use standard local time */
 67         millis += tz.getRawOffset();
 68 
 69         int offset = tz.getOffset(cal.get(Calendar.ERA),
 70                                   cal.get(Calendar.YEAR),
 71                                   cal.get(Calendar.MONTH),
 72                                   cal.get(Calendar.DATE),
 73                                   cal.get(Calendar.DAY_OF_WEEK),
 74                                   millis);
 75 
 76         if (offset != 0) {
 77             SimpleDateFormat format = new SimpleDateFormat("dd MMM HH:mm:ss zzz",
 78                                                            Locale.US);
 79             format.setTimeZone(tz);
 80             errln("Wrong DST transition: " + tz
 81                   + "\na date just after DST = " + format.format(date)
 82                   + "\ngetOffset = " + offset);
 83         }
 84     }
 85 
 86     /*
 87      * 4761696: Rewrite SimpleTimeZone to support correct DST transitions
 88      *
 89      * Derived from JCK test cases some of which specify wrong day of week values.
 90      */

 91     public void Test4761696() {
 92         GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
 93 
 94         // test#1
 95         int rawOffset = -43200000;
 96         int saving = 1800000;
 97         int timeOfDay = 84600001;
 98         SimpleTimeZone tz = new SimpleTimeZone(rawOffset, "stz",
 99                                 Calendar.JULY, 1, 0, 0,
100                                 Calendar.JANUARY, 1, 0, 0,
101                                 saving);
102         int year = Integer.MIN_VALUE;
103         tz.setStartYear(year);
104         int offset = tz.getOffset(GregorianCalendar.AD,
105                               year,
106                               Calendar.DECEMBER,
107                               31,
108                               1, // should be SATURDAY
109                               timeOfDay);
110         int y = (int) mod((long)year, 28L); // 28-year cycle
111         cal.clear();
112         cal.set(cal.ERA, cal.AD);
113         cal.set(y, Calendar.DECEMBER, 31);
114         cal.set(cal.MILLISECOND, timeOfDay);
115         long localtime = cal.getTimeInMillis() + rawOffset; // local standard time
116 
117         cal.clear();
118         cal.set(cal.ERA, cal.AD);
119         cal.set(y + 1, Calendar.JANUARY, 1);
120         cal.set(cal.MILLISECOND, -saving);
121         long endTime = cal.getTimeInMillis() + rawOffset;
122         long expectedOffset = (localtime < endTime) ? rawOffset + saving : rawOffset;
123         if (offset != expectedOffset) {
124             errln("test#1: wrong offset: got "+offset+", expected="+expectedOffset);
125         }
126 
127         // test#2
128         saving = 1;
129         timeOfDay = 0;
130         tz = new SimpleTimeZone(rawOffset, "stz",
131                                 Calendar.JULY, 1, 0, 0,
132                                 Calendar.JANUARY, 1, 0, 0,
133                                 saving);
134         tz.setStartYear(year);
135         offset = tz.getOffset(GregorianCalendar.AD,
136                               year,
137                               Calendar.AUGUST,
138                               15,
139                               1, // should be MONDAY
140                               timeOfDay);
141         y = (int) mod((long)year, 28L); // 28-year cycle
142         cal.clear();
143         cal.set(y, Calendar.AUGUST, 15);
144         cal.set(cal.MILLISECOND, timeOfDay);
145         localtime = cal.getTimeInMillis() + rawOffset; // local standard time
146 
147         cal.clear();
148         cal.set(y + 1, Calendar.JANUARY, 1);
149         cal.set(cal.MILLISECOND, -saving);
150         endTime = cal.getTimeInMillis() + rawOffset;
151         expectedOffset = (localtime < endTime) ? rawOffset + saving : rawOffset;
152         if (offset != expectedOffset) {
153             errln("Wrong offset: got "+offset+", expected="+expectedOffset);
154         }
155 
156         rawOffset = 43200000;
157         saving = 1;
158         timeOfDay = 3599998;
159         tz = new SimpleTimeZone(rawOffset, "stz",
160                                 Calendar.JULY, 1, 0, 3600000,
161                                 Calendar.JANUARY, 1, 0, 3600000,
162                                 saving);
163         tz.setStartYear(year);
164         offset = tz.getOffset(GregorianCalendar.AD,
165                               year,
166                               Calendar.JANUARY,
167                               1,
168                               1,
169                               timeOfDay);
170         y = (int) mod((long)year, 28L); // 28-year cycle
171         cal.clear();
172         cal.set(y, Calendar.JANUARY, 1);
173         cal.set(cal.MILLISECOND, timeOfDay);
174         localtime = cal.getTimeInMillis() + rawOffset; // local standard time
175 
176         cal.clear();
177         cal.set(y + 1, Calendar.JANUARY, 1);
178         cal.set(cal.MILLISECOND, 3600000-saving);
179         endTime = cal.getTimeInMillis() + rawOffset;
180         expectedOffset = (localtime < endTime) ? rawOffset + saving : rawOffset;
181         if (offset != expectedOffset) {
182             errln("test#2: wrong offset: got "+offset+", expected="+expectedOffset);
183         }
184 
185         // test#3
186         rawOffset = -43200000;
187         saving = 1800000;
188         timeOfDay = 84600001;
189         tz = new SimpleTimeZone(rawOffset, "stz",
190                                 Calendar.SEPTEMBER, 1, 0, 0,
191                                 Calendar.MARCH, 1, 0, 0,
192                                 saving);
193         tz.setStartYear(year);
194         offset = tz.getOffset(GregorianCalendar.AD,
195                               year,
196                               Calendar.FEBRUARY,
197                               28,
198                               1,
199                               timeOfDay);
200         y = (int) mod((long)year, 28L); // 28-year cycle
201         cal.clear();
202         cal.set(y, Calendar.FEBRUARY, 28);
203         cal.set(cal.MILLISECOND, timeOfDay);
204         localtime = cal.getTimeInMillis() + rawOffset; // local standard time
205 
206         cal.clear();
207         cal.set(y, Calendar.MARCH, 1);
208         cal.set(cal.MILLISECOND, -saving);
209         endTime = cal.getTimeInMillis() + rawOffset;
210         expectedOffset = (localtime < endTime) ? rawOffset + saving : rawOffset;
211         if (offset != expectedOffset) {
212             errln("test#3: wrong offset: got "+offset+", expected="+expectedOffset);
213         }
214 
215         // test#4
216         rawOffset = -43200000;
217         saving = 1;
218         timeOfDay = 0;
219         tz = new SimpleTimeZone(rawOffset, "stz",
220                                 Calendar.JANUARY, -4, 1, 3600000,
221                                 Calendar.JULY, -4, 1, 3600000,
222                                 saving);
223         tz.setStartYear(year);
224         offset = tz.getOffset(GregorianCalendar.AD,
225                               year,
226                               Calendar.JANUARY,
227                               10,
228                               2, // should be 1 (SUNDAY)
229                               timeOfDay);
230         y = (int) mod((long)year, 28L); // 28-year cycle
231         cal.clear();
232         cal.set(y, Calendar.JANUARY, 10);
233         cal.set(cal.MILLISECOND, timeOfDay);
234         localtime = cal.getTimeInMillis() + rawOffset; // local standard time
235 
236         cal.clear();
237         cal.set(cal.YEAR, y);
238         cal.set(cal.MONTH, Calendar.JANUARY);
239         cal.set(cal.DAY_OF_MONTH, 8);
240         cal.set(cal.WEEK_OF_MONTH, cal.getActualMaximum(cal.WEEK_OF_MONTH)-4+1);
241         cal.set(cal.DAY_OF_WEEK, 1);
242         cal.set(cal.MILLISECOND, 3600000-saving);
243         long startTime = cal.getTimeInMillis() + rawOffset;
244         expectedOffset = (localtime >= startTime) ? rawOffset + saving : rawOffset;
245         if (offset != expectedOffset) {
246             errln("test#4: wrong offset: got "+offset+", expected="+expectedOffset);
247         }
248 
249         // test#5
250         rawOffset = 0;
251         saving = 3600000;
252         timeOfDay = 7200000;
253         year = 1982;
254         tz = new SimpleTimeZone(rawOffset, "stz",
255                                 Calendar.APRIL, 1, 0, 7200000,
256                                 Calendar.OCTOBER, 10, 0, 7200000,
257                                 saving);
258         offset = tz.getOffset(GregorianCalendar.AD,
259                               year,
260                               Calendar.OCTOBER,
261                               10,
262                               1,
263                               timeOfDay);
264         cal.clear();
265         cal.set(year, Calendar.OCTOBER, 10);
266         cal.set(cal.MILLISECOND, timeOfDay);
267         localtime = cal.getTimeInMillis() + rawOffset; // local standard time
268 
269         cal.clear();
270         cal.set(year, Calendar.OCTOBER, 10);
271         cal.set(cal.MILLISECOND, 7200000-saving);
272         endTime = cal.getTimeInMillis() + rawOffset;
273         expectedOffset = (localtime < endTime) ? rawOffset + saving : rawOffset;
274         if (offset != expectedOffset) {
275             errln("test#5: wrong offset: got "+offset+", expected="+expectedOffset);
276         }
277     }
278 
279     public static final long floorDivide(long n, long d) {
280         return ((n >= 0) ?
281                 (n / d) : (((n + 1L) / d) - 1L));
282     }
283 
284     public static final long mod(long x, long y) {
285         return (x - y * floorDivide(x, y));
286     }
287 }

  1 /*
  2  * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 
 24 /*
 25  * @test
 26  * @bug 4278609 4761696

 27  * @summary Make sure to handle DST transition ending at 0:00 January 1.
 28  * @run junit TransitionTest
 29  */
 30 
 31 import java.text.SimpleDateFormat;
 32 import java.util.Calendar;
 33 import java.util.Date;
 34 import java.util.GregorianCalendar;
 35 import java.util.Locale;
 36 import java.util.SimpleTimeZone;
 37 import java.util.TimeZone;
 38 
 39 import org.junit.jupiter.api.Test;
 40 
 41 import static org.junit.jupiter.api.Assertions.fail;
 42 
 43 public class TransitionTest {
 44 
 45     @Test
 46     public void Test4278609() {
 47         SimpleTimeZone tz = new SimpleTimeZone(0, "MyTimeZone",
 48                                /* DST start day: August, 1, 0:00 */
 49                                Calendar.AUGUST, 1, 0, 0,
 50                                /* DST end day: January, 1, 0:00 (wall-clock)*/
 51                                Calendar.JANUARY, 1, 0, 0,
 52                                60 * 60 * 1000);
 53 
 54         Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
 55 
 56         // setting a date using GMT zone just after the end rule of tz zone
 57         cal.clear();
 58         cal.set(Calendar.ERA, GregorianCalendar.AD);
 59         cal.set(1998, Calendar.DECEMBER, 31, 23, 01, 00);
 60 
 61         Date date = cal.getTime();
 62 
 63         int millis = cal.get(Calendar.HOUR_OF_DAY) * 3600000
 64                      + cal.get(Calendar.MINUTE) * 60000
 65                      + cal.get(Calendar.SECOND) * 1000
 66                      + cal.get(Calendar.MILLISECOND);
 67         /* we must use standard local time */
 68         millis += tz.getRawOffset();
 69 
 70         int offset = tz.getOffset(cal.get(Calendar.ERA),
 71                                   cal.get(Calendar.YEAR),
 72                                   cal.get(Calendar.MONTH),
 73                                   cal.get(Calendar.DATE),
 74                                   cal.get(Calendar.DAY_OF_WEEK),
 75                                   millis);
 76 
 77         if (offset != 0) {
 78             SimpleDateFormat format = new SimpleDateFormat("dd MMM HH:mm:ss zzz",
 79                                                            Locale.US);
 80             format.setTimeZone(tz);
 81             fail("Wrong DST transition: " + tz
 82                   + "\na date just after DST = " + format.format(date)
 83                   + "\ngetOffset = " + offset);
 84         }
 85     }
 86 
 87     /*
 88      * 4761696: Rewrite SimpleTimeZone to support correct DST transitions
 89      *
 90      * Derived from JCK test cases some of which specify wrong day of week values.
 91      */
 92     @Test
 93     public void Test4761696() {
 94         GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
 95 
 96         // test#1
 97         int rawOffset = -43200000;
 98         int saving = 1800000;
 99         int timeOfDay = 84600001;
100         SimpleTimeZone tz = new SimpleTimeZone(rawOffset, "stz",
101                                 Calendar.JULY, 1, 0, 0,
102                                 Calendar.JANUARY, 1, 0, 0,
103                                 saving);
104         int year = Integer.MIN_VALUE;
105         tz.setStartYear(year);
106         int offset = tz.getOffset(GregorianCalendar.AD,
107                               year,
108                               Calendar.DECEMBER,
109                               31,
110                               1, // should be SATURDAY
111                               timeOfDay);
112         int y = (int) mod((long)year, 28L); // 28-year cycle
113         cal.clear();
114         cal.set(cal.ERA, cal.AD);
115         cal.set(y, Calendar.DECEMBER, 31);
116         cal.set(cal.MILLISECOND, timeOfDay);
117         long localtime = cal.getTimeInMillis() + rawOffset; // local standard time
118 
119         cal.clear();
120         cal.set(cal.ERA, cal.AD);
121         cal.set(y + 1, Calendar.JANUARY, 1);
122         cal.set(cal.MILLISECOND, -saving);
123         long endTime = cal.getTimeInMillis() + rawOffset;
124         long expectedOffset = (localtime < endTime) ? rawOffset + saving : rawOffset;
125         if (offset != expectedOffset) {
126             fail("test#1: wrong offset: got "+offset+", expected="+expectedOffset);
127         }
128 
129         // test#2
130         saving = 1;
131         timeOfDay = 0;
132         tz = new SimpleTimeZone(rawOffset, "stz",
133                                 Calendar.JULY, 1, 0, 0,
134                                 Calendar.JANUARY, 1, 0, 0,
135                                 saving);
136         tz.setStartYear(year);
137         offset = tz.getOffset(GregorianCalendar.AD,
138                               year,
139                               Calendar.AUGUST,
140                               15,
141                               1, // should be MONDAY
142                               timeOfDay);
143         y = (int) mod((long)year, 28L); // 28-year cycle
144         cal.clear();
145         cal.set(y, Calendar.AUGUST, 15);
146         cal.set(cal.MILLISECOND, timeOfDay);
147         localtime = cal.getTimeInMillis() + rawOffset; // local standard time
148 
149         cal.clear();
150         cal.set(y + 1, Calendar.JANUARY, 1);
151         cal.set(cal.MILLISECOND, -saving);
152         endTime = cal.getTimeInMillis() + rawOffset;
153         expectedOffset = (localtime < endTime) ? rawOffset + saving : rawOffset;
154         if (offset != expectedOffset) {
155             fail("Wrong offset: got "+offset+", expected="+expectedOffset);
156         }
157 
158         rawOffset = 43200000;
159         saving = 1;
160         timeOfDay = 3599998;
161         tz = new SimpleTimeZone(rawOffset, "stz",
162                                 Calendar.JULY, 1, 0, 3600000,
163                                 Calendar.JANUARY, 1, 0, 3600000,
164                                 saving);
165         tz.setStartYear(year);
166         offset = tz.getOffset(GregorianCalendar.AD,
167                               year,
168                               Calendar.JANUARY,
169                               1,
170                               1,
171                               timeOfDay);
172         y = (int) mod((long)year, 28L); // 28-year cycle
173         cal.clear();
174         cal.set(y, Calendar.JANUARY, 1);
175         cal.set(cal.MILLISECOND, timeOfDay);
176         localtime = cal.getTimeInMillis() + rawOffset; // local standard time
177 
178         cal.clear();
179         cal.set(y + 1, Calendar.JANUARY, 1);
180         cal.set(cal.MILLISECOND, 3600000-saving);
181         endTime = cal.getTimeInMillis() + rawOffset;
182         expectedOffset = (localtime < endTime) ? rawOffset + saving : rawOffset;
183         if (offset != expectedOffset) {
184             fail("test#2: wrong offset: got "+offset+", expected="+expectedOffset);
185         }
186 
187         // test#3
188         rawOffset = -43200000;
189         saving = 1800000;
190         timeOfDay = 84600001;
191         tz = new SimpleTimeZone(rawOffset, "stz",
192                                 Calendar.SEPTEMBER, 1, 0, 0,
193                                 Calendar.MARCH, 1, 0, 0,
194                                 saving);
195         tz.setStartYear(year);
196         offset = tz.getOffset(GregorianCalendar.AD,
197                               year,
198                               Calendar.FEBRUARY,
199                               28,
200                               1,
201                               timeOfDay);
202         y = (int) mod((long)year, 28L); // 28-year cycle
203         cal.clear();
204         cal.set(y, Calendar.FEBRUARY, 28);
205         cal.set(cal.MILLISECOND, timeOfDay);
206         localtime = cal.getTimeInMillis() + rawOffset; // local standard time
207 
208         cal.clear();
209         cal.set(y, Calendar.MARCH, 1);
210         cal.set(cal.MILLISECOND, -saving);
211         endTime = cal.getTimeInMillis() + rawOffset;
212         expectedOffset = (localtime < endTime) ? rawOffset + saving : rawOffset;
213         if (offset != expectedOffset) {
214             fail("test#3: wrong offset: got "+offset+", expected="+expectedOffset);
215         }
216 
217         // test#4
218         rawOffset = -43200000;
219         saving = 1;
220         timeOfDay = 0;
221         tz = new SimpleTimeZone(rawOffset, "stz",
222                                 Calendar.JANUARY, -4, 1, 3600000,
223                                 Calendar.JULY, -4, 1, 3600000,
224                                 saving);
225         tz.setStartYear(year);
226         offset = tz.getOffset(GregorianCalendar.AD,
227                               year,
228                               Calendar.JANUARY,
229                               10,
230                               2, // should be 1 (SUNDAY)
231                               timeOfDay);
232         y = (int) mod((long)year, 28L); // 28-year cycle
233         cal.clear();
234         cal.set(y, Calendar.JANUARY, 10);
235         cal.set(cal.MILLISECOND, timeOfDay);
236         localtime = cal.getTimeInMillis() + rawOffset; // local standard time
237 
238         cal.clear();
239         cal.set(cal.YEAR, y);
240         cal.set(cal.MONTH, Calendar.JANUARY);
241         cal.set(cal.DAY_OF_MONTH, 8);
242         cal.set(cal.WEEK_OF_MONTH, cal.getActualMaximum(cal.WEEK_OF_MONTH)-4+1);
243         cal.set(cal.DAY_OF_WEEK, 1);
244         cal.set(cal.MILLISECOND, 3600000-saving);
245         long startTime = cal.getTimeInMillis() + rawOffset;
246         expectedOffset = (localtime >= startTime) ? rawOffset + saving : rawOffset;
247         if (offset != expectedOffset) {
248             fail("test#4: wrong offset: got "+offset+", expected="+expectedOffset);
249         }
250 
251         // test#5
252         rawOffset = 0;
253         saving = 3600000;
254         timeOfDay = 7200000;
255         year = 1982;
256         tz = new SimpleTimeZone(rawOffset, "stz",
257                                 Calendar.APRIL, 1, 0, 7200000,
258                                 Calendar.OCTOBER, 10, 0, 7200000,
259                                 saving);
260         offset = tz.getOffset(GregorianCalendar.AD,
261                               year,
262                               Calendar.OCTOBER,
263                               10,
264                               1,
265                               timeOfDay);
266         cal.clear();
267         cal.set(year, Calendar.OCTOBER, 10);
268         cal.set(cal.MILLISECOND, timeOfDay);
269         localtime = cal.getTimeInMillis() + rawOffset; // local standard time
270 
271         cal.clear();
272         cal.set(year, Calendar.OCTOBER, 10);
273         cal.set(cal.MILLISECOND, 7200000-saving);
274         endTime = cal.getTimeInMillis() + rawOffset;
275         expectedOffset = (localtime < endTime) ? rawOffset + saving : rawOffset;
276         if (offset != expectedOffset) {
277             fail("test#5: wrong offset: got "+offset+", expected="+expectedOffset);
278         }
279     }
280 
281     public static final long floorDivide(long n, long d) {
282         return ((n >= 0) ?
283                 (n / d) : (((n + 1L) / d) - 1L));
284     }
285 
286     public static final long mod(long x, long y) {
287         return (x - y * floorDivide(x, y));
288     }
289 }
< prev index next >