20

I'd like to know the simplest way, in Java, to get a list of dates in the future where daylight savings time will change.

One rather inellegant way to do this would be to simply iterate over a bunch of years' worth of days, testing them against TimeZone.inDaylightTime(). This will work, and I'm not worried about efficiency since this will only need to run every time my app starts, but I wonder if there's a simpler way.

If you're wondering why I'm doing this, it's because I have a javascript app which needs to handle third-party data containing UTC timestamps. I want a reliable way to translate from GMT to EST on the client side. See Javascript -- Unix Time to Specific Time Zone I've written some javascript which will do it, but I want to get precise transition dates from the server.

Community
  • 1
  • 1
morgancodes
  • 25,055
  • 38
  • 135
  • 187
  • 2
    See this question: http://stackoverflow.com/questions/581581/find-dst-transition-timestamp-with-java-util-timezone – Rich Seller Sep 19 '09 at 21:04

2 Answers2

34

Joda Time (as ever) makes this really easy due to the DateTimeZone.nextTransition method. For example:

import org.joda.time.*;
import org.joda.time.format.*;

public class Test
{    
    public static void main(String[] args)
    {
        DateTimeZone zone = DateTimeZone.forID("Europe/London");        
        DateTimeFormatter format = DateTimeFormat.mediumDateTime();

        long current = System.currentTimeMillis();
        for (int i=0; i < 100; i++)
        {
            long next = zone.nextTransition(current);
            if (current == next)
            {
                break;
            }
            System.out.println (format.print(next) + " Into DST? " 
                                + !zone.isStandardOffset(next));
            current = next;
        }
    }
}

Output:

25-Oct-2009 01:00:00 Into DST? false
28-Mar-2010 02:00:00 Into DST? true
31-Oct-2010 01:00:00 Into DST? false
27-Mar-2011 02:00:00 Into DST? true
30-Oct-2011 01:00:00 Into DST? false
25-Mar-2012 02:00:00 Into DST? true
28-Oct-2012 01:00:00 Into DST? false
31-Mar-2013 02:00:00 Into DST? true
27-Oct-2013 01:00:00 Into DST? false
30-Mar-2014 02:00:00 Into DST? true
26-Oct-2014 01:00:00 Into DST? false
29-Mar-2015 02:00:00 Into DST? true
25-Oct-2015 01:00:00 Into DST? false
...

With Java 8, you can get the same information using ZoneRules with its nextTransition and previousTransition methods.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • +1 for the 'sample coming' idea (as well as the rest of answer, of course) – akf Sep 19 '09 at 21:04
  • Of course, projecting that far ahead is pretty speculative. The US has tinkered with the DST dates lately, and may again. – brianary Sep 24 '09 at 18:13
  • This year first DST transition date is March 14 2010 (which happened a few days ago). But your script specifies 28-Mar-2010. Am I missing something ? – Philippe Carriere Mar 16 '10 at 14:34
  • 7
    @Silence: It's the 28th of March in London, which is the time zone specified in the code. Not everyone is in the US... – Jon Skeet Mar 16 '10 at 15:00
  • Right. That's what I was missing. Thank you. – Philippe Carriere Mar 16 '10 at 17:21
  • +1 But whoever uses this solution must remeber that the joda-time compiles the zoninfo files into its jars and doesn't uses the JDK's files, as stated here http://joda-time.sourceforge.net/tz_update.html – A.B.Cade Sep 12 '13 at 07:09
  • I wish there was a way to achieve this without any third party api – bluelurker Jan 01 '15 at 08:31
  • 3
    @bluelurker: With Java 8, there is - you can use `ZoneRules.nextTransition` and `ZoneRules.previousTransition`. I've edited a link into my answer. – Jon Skeet Jan 01 '15 at 08:42
7

java.time

The modern answer uses java.time, the modern Java date and time API.

    ZoneId zone = ZoneId.of("Europe/London");
    ZoneRules rules = zone.getRules();
    ZonedDateTime now = ZonedDateTime.now(zone);
    ZoneOffsetTransition transition = rules.nextTransition(now.toInstant());
    Instant max = now.plusYears(15).toInstant();
    while (transition != null && transition.getInstant().isBefore(max)) {
        System.out.println(transition);
        transition = rules.nextTransition(transition.getInstant());
    }

Output, abbreviated:

Transition[Overlap at 2019-10-27T02:00+01:00 to Z]
Transition[Gap at 2020-03-29T01:00Z to +01:00]
Transition[Overlap at 2020-10-25T02:00+01:00 to Z]
Transition[Gap at 2021-03-28T01:00Z to +01:00]
Transition[Overlap at 2021-10-31T02:00+01:00 to Z]
Transition[Gap at 2022-03-27T01:00Z to +01:00]
Transition[Overlap at 2022-10-30T02:00+01:00 to Z]
(cut)
Transition[Overlap at 2033-10-30T02:00+01:00 to Z]
Transition[Gap at 2034-03-26T01:00Z to +01:00]

I would not put too much trust in the data, though. I am not sure what happens with time in the UK after Brexit (and after EU may abandon summer time (DST) in 2021).

Link: Oracle tutorial: Date Time explaining how to use java.time.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161