6936350: API clarification needed on useDaylightTime() for timezones that have defined usage dates
Reviewed-by: peytoia
--- a/jdk/src/share/classes/java/util/SimpleTimeZone.java Tue Feb 15 16:40:25 2011 +0300
+++ b/jdk/src/share/classes/java/util/SimpleTimeZone.java Wed Feb 16 16:51:21 2011 +0900
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -825,10 +825,7 @@
* @since 1.2
*/
public int getDSTSavings() {
- if (useDaylight) {
- return dstSavings;
- }
- return 0;
+ return useDaylight ? dstSavings : 0;
}
/**
@@ -842,6 +839,20 @@
}
/**
+ * Returns {@code true} if this {@code SimpleTimeZone} observes
+ * Daylight Saving Time. This method is equivalent to {@link
+ * #useDaylightTime()}.
+ *
+ * @return {@code true} if this {@code SimpleTimeZone} observes
+ * Daylight Saving Time; {@code false} otherwise.
+ * @since 1.7
+ */
+ @Override
+ public boolean observesDaylightTime() {
+ return useDaylightTime();
+ }
+
+ /**
* Queries if the given date is in daylight saving time.
* @return true if daylight saving time is in effective at the
* given date; false otherwise.
--- a/jdk/src/share/classes/java/util/TimeZone.java Tue Feb 15 16:40:25 2011 +0300
+++ b/jdk/src/share/classes/java/util/TimeZone.java Wed Feb 16 16:51:21 2011 +0900
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -455,17 +455,28 @@
/**
* Returns the amount of time to be added to local standard time
* to get local wall clock time.
- * <p>
- * The default implementation always returns 3600000 milliseconds
- * (i.e., one hour) if this time zone observes Daylight Saving
- * Time. Otherwise, 0 (zero) is returned.
- * <p>
- * If an underlying TimeZone implementation subclass supports
- * historical Daylight Saving Time changes, this method returns
- * the known latest daylight saving value.
+ *
+ * <p>The default implementation returns 3600000 milliseconds
+ * (i.e., one hour) if a call to {@link #useDaylightTime()}
+ * returns {@code true}. Otherwise, 0 (zero) is returned.
+ *
+ * <p>If an underlying {@code TimeZone} implementation subclass
+ * supports historical and future Daylight Saving Time schedule
+ * changes, this method returns the amount of saving time of the
+ * last known Daylight Saving Time rule that can be a future
+ * prediction.
+ *
+ * <p>If the amount of saving time at any given time stamp is
+ * required, construct a {@link Calendar} with this {@code
+ * TimeZone} and the time stamp, and call {@link Calendar#get(int)
+ * Calendar.get}{@code (}{@link Calendar#DST_OFFSET}{@code )}.
*
* @return the amount of saving time in milliseconds
* @since 1.4
+ * @see #inDaylightTime(Date)
+ * @see #getOffset(long)
+ * @see #getOffset(int,int,int,int,int,int)
+ * @see Calendar#ZONE_OFFSET
*/
public int getDSTSavings() {
if (useDaylightTime()) {
@@ -475,24 +486,51 @@
}
/**
- * Queries if this time zone uses daylight savings time.
- * <p>
- * If an underlying <code>TimeZone</code> implementation subclass
- * supports historical Daylight Saving Time schedule changes, the
- * method refers to the latest Daylight Saving Time schedule
- * information.
+ * Queries if this {@code TimeZone} uses Daylight Saving Time.
*
- * @return true if this time zone uses daylight savings time,
- * false, otherwise.
+ * <p>If an underlying {@code TimeZone} implementation subclass
+ * supports historical and future Daylight Saving Time schedule
+ * changes, this method refers to the last known Daylight Saving Time
+ * rule that can be a future prediction and may not be the same as
+ * the current rule. Consider calling {@link #observesDaylightTime()}
+ * if the current rule should also be taken into account.
+ *
+ * @return {@code true} if this {@code TimeZone} uses Daylight Saving Time,
+ * {@code false}, otherwise.
+ * @see #inDaylightTime(Date)
+ * @see Calendar#DST_OFFSET
*/
public abstract boolean useDaylightTime();
/**
- * Queries if the given date is in daylight savings time in
- * this time zone.
- * @param date the given Date.
- * @return true if the given date is in daylight savings time,
- * false, otherwise.
+ * Returns {@code true} if this {@code TimeZone} is currently in
+ * Daylight Saving Time, or if a transition from Standard Time to
+ * Daylight Saving Time occurs at any future time.
+ *
+ * <p>The default implementation returns {@code true} if
+ * {@code useDaylightTime()} or {@code inDaylightTime(new Date())}
+ * returns {@code true}.
+ *
+ * @return {@code true} if this {@code TimeZone} is currently in
+ * Daylight Saving Time, or if a transition from Standard Time to
+ * Daylight Saving Time occurs at any future time; {@code false}
+ * otherwise.
+ * @since 1.7
+ * @see #useDaylightTime()
+ * @see #inDaylightTime(Date)
+ * @see Calendar#DST_OFFSET
+ */
+ public boolean observesDaylightTime() {
+ return useDaylightTime() || inDaylightTime(new Date());
+ }
+
+ /**
+ * Queries if the given {@code date} is in Daylight Saving Time in
+ * this {@code TimeZone}.
+ *
+ * @param date the given {@code Date}.
+ * @return {@code true} if the given {@code date} is in Daylight Saving Time,
+ * {@code false}, otherwise.
*/
abstract public boolean inDaylightTime(Date date);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/TimeZone/DaylightTimeTest.java Wed Feb 16 16:51:21 2011 +0900
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 6936350
+ * @summary Test case for TimeZone.observesDaylightTime()
+ */
+
+import java.util.*;
+import static java.util.GregorianCalendar.*;
+
+public class DaylightTimeTest {
+ private static final int ONE_HOUR = 60 * 60 * 1000; // one hour
+ private static final int INTERVAL = 24 * ONE_HOUR; // one day
+ private static final String[] ZONES = TimeZone.getAvailableIDs();
+ private static int errors = 0;
+
+ public static void main(String[] args) {
+
+ // Test default TimeZone
+ for (String id : ZONES) {
+ TimeZone tz = TimeZone.getTimeZone(id);
+ long now = System.currentTimeMillis();
+ boolean observes = tz.observesDaylightTime();
+ boolean found = findDSTTransition(tz, now);
+ if (observes != found) {
+ // There's a critical section. If DST ends after the
+ // System.currentTimeMills() call, there should be
+ // inconsistency in the determination. Try the same
+ // thing again to see the inconsistency was due to the
+ // critical section.
+ now = System.currentTimeMillis();
+ observes = tz.observesDaylightTime();
+ found = findDSTTransition(tz, now);
+ if (observes != found) {
+ System.err.printf("%s: observesDaylightTime() should return %s at %d%n",
+ tz.getID(), found, now);
+ errors++;
+ }
+ }
+ }
+
+ // Test SimpleTimeZone in which observesDaylightTime() is
+ // equivalent to useDaylightTime().
+ testSimpleTimeZone(new SimpleTimeZone(-8*ONE_HOUR, "X",
+ APRIL, 1, -SUNDAY, 2*ONE_HOUR,
+ OCTOBER, -1, SUNDAY, 2*ONE_HOUR,
+ 1*ONE_HOUR));
+ testSimpleTimeZone(new SimpleTimeZone(-8*ONE_HOUR, "Y"));
+
+ if (errors > 0) {
+ throw new RuntimeException("DaylightTimeTest: failed");
+ }
+ }
+
+ /**
+ * Returns true if it's `now' in DST or there's any
+ * standard-to-daylight transition within 50 years after `now'.
+ */
+ private static boolean findDSTTransition(TimeZone tz, long now) {
+ GregorianCalendar cal = new GregorianCalendar(tz, Locale.US);
+ cal.setTimeInMillis(now);
+ cal.add(YEAR, 50);
+ long end = cal.getTimeInMillis();
+
+ for (long t = now; t < end; t += INTERVAL) {
+ cal.setTimeInMillis(t);
+ if (cal.get(DST_OFFSET) > 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static void testSimpleTimeZone(SimpleTimeZone stz) {
+ if (stz.useDaylightTime() != stz.observesDaylightTime()) {
+ System.err.printf("Failed: useDaylightTime=%b, observesDaylightTime()=%b%n\t%s%n",
+ stz.useDaylightTime(),stz.observesDaylightTime(), stz);
+ errors++;
+ }
+ }
+}