Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find DST transition timestamp with java.util.TimeZone

Tags:

java

jodatime

Is it possible to get the previous and next DST transition timestamp with the Java Calendar/Date/TimeZone API?
With Joda-Time I can write:

DateMidnight today = new DateMidnight(2009, 2, 24);
DateTimeZone zone = today.getZone();

DateTime previousTransition =
    new DateTime(zone.previousTransition(today.getMillis()));
// 2008-10-26T02:59:59.999+02:00 for Europe/Berlin
System.out.println(previousTransition);

DateTime nextTransition =
    new DateTime(zone.nextTransition(today.getMillis()));
// 2009-03-29T03:00:00.000+02:00 for Europe/Berlin
System.out.println(nextTransition);

Is there way to do this with the standard Java APIs?

like image 796
Ludwig Wensauer Avatar asked Dec 22 '22 12:12

Ludwig Wensauer


2 Answers

There's no such functionality in java Date/Calendar/TimeZone API

like image 137
tehvan Avatar answered Jan 05 '23 08:01

tehvan


The best I came up with, when I needed such functionality, is to use a Calendar and iterate through entire year, in specified time zone, and ask if each hour of each day is it the begging or ending of DST.

You have to do it like that because on Sun's JVM, the implementation of TimeZone (sun.util.calendar.ZoneInfo) holds data about time zone transitions in some kind of "compiled" form.

Code goes something like this:

public class Dst {
    Date start;
    Date end;

    public static Dst calculate(TimeZone tz, int year) {
        final Calendar c = Calendar.getInstance(tz);
        c.setLenient(false);
        c.set(year, Calendar.JANUARY, 1, 1, 0, 0);
        c.set(Calendar.MILLISECOND, 0);

        if (tz.getDSTSavings() == 0) {
            return null;
        }

        Dst dst = new Dst();

        boolean flag = false;

        do {
            Date date = c.getTime();
            boolean daylight = tz.inDaylightTime(date);

            if (daylight && !flag) {
                flag = true;
                dst.start = date;
            }
            else if (!daylight && flag) {
                flag = false;
                dst.end = date;
            }

            c.add(Calendar.HOUR_OF_DAY, 1);
        }
        while (c.get(Calendar.YEAR) == year);

        return dst;
    }
}

Of course, it would make sense to cache/memoize the result of these calculations etc.

Hope this helps.

like image 44
javashlook Avatar answered Jan 05 '23 07:01

javashlook