From 5bf712eff4e8d7b4675db3d17795e829f9ca41ea Mon Sep 17 00:00:00 2001 From: okutsu Date: Wed, 16 Feb 2011 16:51:21 +0900 Subject: [PATCH] 6936350: API clarification needed on useDaylightTime() for timezones that have defined usage dates Reviewed-by: peytoia --- .../classes/java/util/SimpleTimeZone.java | 21 +++- src/share/classes/java/util/TimeZone.java | 82 ++++++++++---- test/java/util/TimeZone/DaylightTimeTest.java | 103 ++++++++++++++++++ 3 files changed, 179 insertions(+), 27 deletions(-) create mode 100644 test/java/util/TimeZone/DaylightTimeTest.java diff --git a/src/share/classes/java/util/SimpleTimeZone.java b/src/share/classes/java/util/SimpleTimeZone.java index 864277332..ef70b960e 100644 --- a/src/share/classes/java/util/SimpleTimeZone.java +++ b/src/share/classes/java/util/SimpleTimeZone.java @@ -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 @@ public class SimpleTimeZone extends TimeZone { * @since 1.2 */ public int getDSTSavings() { - if (useDaylight) { - return dstSavings; - } - return 0; + return useDaylight ? dstSavings : 0; } /** @@ -841,6 +838,20 @@ public class SimpleTimeZone extends TimeZone { return useDaylight; } + /** + * 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 diff --git a/src/share/classes/java/util/TimeZone.java b/src/share/classes/java/util/TimeZone.java index ca62e0ed7..9799be601 100644 --- a/src/share/classes/java/util/TimeZone.java +++ b/src/share/classes/java/util/TimeZone.java @@ -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 @@ abstract public class TimeZone implements Serializable, Cloneable { /** * Returns the amount of time to be added to local standard time * to get local wall clock time. - *

- * The default implementation always returns 3600000 milliseconds - * (i.e., one hour) if this time zone observes Daylight Saving - * Time. Otherwise, 0 (zero) is returned. - *

- * If an underlying TimeZone implementation subclass supports - * historical Daylight Saving Time changes, this method returns - * the known latest daylight saving value. + * + *

The default implementation returns 3600000 milliseconds + * (i.e., one hour) if a call to {@link #useDaylightTime()} + * returns {@code true}. Otherwise, 0 (zero) is returned. + * + *

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. + * + *

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 @@ abstract public class TimeZone implements Serializable, Cloneable { } /** - * Queries if this time zone uses daylight savings time. - *

- * If an underlying TimeZone 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. + * + *

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 true if this time zone uses daylight savings time, - * false, otherwise. + * @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. + * + *

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); diff --git a/test/java/util/TimeZone/DaylightTimeTest.java b/test/java/util/TimeZone/DaylightTimeTest.java new file mode 100644 index 000000000..4b637136f --- /dev/null +++ b/test/java/util/TimeZone/DaylightTimeTest.java @@ -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++; + } + } +} -- GitLab