4

I have a date range (start and end date) and require to know whether this falls within a Daylight Saving change over.

Is there any Java API available to check this or any Java code to achieve this?

bpa.mdl
  • 396
  • 1
  • 5
  • 19
  • Please refer to: https://stackoverflow.com/questions/2532729/daylight-saving-time-and-time-zone-best-practices – Kohei TAMURA Jun 16 '17 at 10:01
  • Similar but not a duplicate: [Determine Whether Daylight Savings Time (DST) is Active in Java for a Specified Date](https://stackoverflow.com/questions/1060479/determine-whether-daylight-savings-time-dst-is-active-in-java-for-a-specified) – Basil Bourque Jun 16 '17 at 17:44

2 Answers2

4

Daylight Saving changes occur at different dates in each country/region, so the first thing to know is the name of the timezone you're checking.

I'm writing this answer using both Joda-Time and the new Java Date/Time API and both use the IANA's list of timezone names (in the format Continent/City). Both API's also avoid to use the 3-letter names because they are ambiguous and not standard.

For the code below I'm gonna use America/Sao_Paulo (the timezone where I live, which has DST changes every year), but you can replace it with the timezone you want.

The code below shows you how to check if a date is in DST and find the next date when a DST change will occur. So, if you have a start and end dates and want to know if both are in within a DST change, you can check if both are in DST or not and also find the next and previous DST changes (and check if the dates are between those changes - it's not clear to me how your check should be done).


Also be aware that Joda-Time is in maintainance mode and is being replaced by the new APIs, so I don't recommend start a new project with it. Even in joda's website it says: "Note that Joda-Time is considered to be a largely “finished” project. No major enhancements are planned. If using Java SE 8, please migrate to java.time (JSR-310).".


Joda-Time

You can use the org.joda.time.DateTimeZone class. To know all the available timezones, call DateTimeZone.getAvailableIDs().

The code below checks if a date is in DST and also finds the next date when a DST change will occur:

// create timezone object
DateTimeZone zone = DateTimeZone.forID("America/Sao_Paulo");

// check if a date is in DST
DateTime inDst = new DateTime(2017, 1, 1, 10, 0, zone);
// isStandardOffset returns false (it's in DST)
System.out.println(zone.isStandardOffset(inDst.getMillis()));
// check when it'll be the next DST change
DateTime nextDstChange = new DateTime(zone.nextTransition(inDst.getMillis()), zone);
System.out.println(nextDstChange); // 2017-02-18T23:00:00.000-03:00

// check if a date is in DST
DateTime noDst = new DateTime(2017, 6, 18, 10, 0, zone);
// isStandardOffset returns true (it's not in DST)
System.out.println(zone.isStandardOffset(noDst.getMillis()));
// check when it'll be the next DST change
nextDstChange = new DateTime(zone.nextTransition(noDst.getMillis()), zone);
System.out.println(nextDstChange); // 2017-10-15T01:00:00.000-02:00

If you want to find the previous DST change (instead of the next), call previousTransition() instead of nextTransition().


Java new Date/Time API

If you're using Java 8, the new java.time API already comes natively.

If you're using Java <= 7, you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, there's the ThreeTenABP (more on how to use it here).

The code below works for both. The only difference is the package names (in Java 8 is java.time and in ThreeTen Backport (or Android's ThreeTenABP) is org.threeten.bp), but the classes and methods names are the same.

The code is very similar to Joda-Time's version. The main differences:

  • While Joda-Time has isStandardOffset() to check if the date is not in DST, the new API has isDaylightSavings() to check if the date is in DST.
  • Joda-Time provides the methods directly in the DateTimeZone class, but the new API has a dedicated class to its DST rules (java.time.zone.ZoneRules)
  • The methods for next and previous transitions return a java.time.zone.ZoneOffsetTransition instead of directly returning a date (this object provides more information about the DST change, as showed below).

Despite all those differences, the idea is very similar:

// create timezone object
ZoneId zone = ZoneId.of("America/Sao_Paulo");
// get the timezone's rules
ZoneRules rules = zone.getRules();

// check if a date is in DST
ZonedDateTime inDST = ZonedDateTime.of(2017, 1, 1, 10, 0, 0, 0, zone);
// isDaylightSavings returns true (it's in DST)
System.out.println(rules.isDaylightSavings(inDST.toInstant()));
// check when it'll be the next DST change
ZoneOffsetTransition nextTransition = rules.nextTransition(inDST.toInstant());
// getInstant() returns the UTC instant; atZone converts to the specified timezone
System.out.println(nextTransition.getInstant().atZone(zone)); // 2017-02-18T23:00-03:00[America/Sao_Paulo]

// you can also check the date/time and offset before and after the DST change
// in this case, at 19/02/2017, the clock is moved 1 hour back (from midnight to 11 PM)
ZonedDateTime beforeDST = ZonedDateTime.of(nextTransition.getDateTimeBefore(), nextTransition.getOffsetBefore());
System.out.println(beforeDST); // 2017-02-19T00:00-02:00
ZonedDateTime afterDST = ZonedDateTime.of(nextTransition.getDateTimeAfter(), nextTransition.getOffsetAfter());
System.out.println(afterDST); // 2017-02-18T23:00-03:00

// check if a date is in DST
ZonedDateTime noDST = ZonedDateTime.of(2017, 6, 1, 10, 0, 0, 0, zone);
// isDaylightSavings returns false (it's not in DST)
System.out.println(rules.isDaylightSavings(noDST.toInstant()));
// check when it'll be the next DST change
nextTransition = rules.nextTransition(noDST.toInstant());
// getInstant() returns the UTC instant; atZone converts to the specified timezone
System.out.println(nextTransition.getInstant().atZone(zone)); // 2017-10-15T01:00-02:00[America/Sao_Paulo]

// you can also check the date/time and offset before and after the DST change
// in this case, at 15/10/2017, the clock is moved 1 hour forward (from midnight to 1 AM)
beforeDST = ZonedDateTime.of(nextTransition.getDateTimeBefore(), nextTransition.getOffsetBefore());
System.out.println(beforeDST); // 2017-10-15T00:00-03:00
afterDST = ZonedDateTime.of(nextTransition.getDateTimeAfter(), nextTransition.getOffsetAfter());
System.out.println(afterDST); // 2017-10-15T01:00-02:00

If you want to find the previous DST change instead of the next, you can call rules.previousTransition() instead of rules.nextTransition().

Community
  • 1
  • 1
3

Certainly there is. There are also more than one. The standard API to use is java.time.

Quite obviously you first need to decide the time zone you want this for.

You tagged your question gmt, and this is easy: GMT does not have daylight saving time (summer time) so there will never be a changeover in your range. If this is what you meant, you need to read no further.

Daylight saving changeover dates are not the same in North America and EU, and on the southern hemisphere they are yet completely different. Also many time zones do not apply DST at all. So get your intended time zone from ZoneId.of(), providing a string in the form continent/city, for example Europe/Stockholm. It accepts a number of cities, I think there’s at least one in every time zone and one in every country. Use ZoneId.getRules() to get a ZoneRules object. Please check the documentation for all the things you can do with this object. I think I would try nextTransistion() passing your start date. If I get a null back, there cannot be a changeover in the range (likely the zone does not apply DST). If I get a ZoneOffsetTransition back, use its getInstant() and check if the Instant lies before your end date.

java.time was described in JSR-310. It is built into Java 8 and later. If you are not yet using Java 8, use the ThreeTen Backport.

You tagged your question jodatime, and yes, Joda-Time should be an option too.

Note that Joda-Time is considered to be a largely “finished” project. No major enhancements are planned. If using Java SE 8, please migrate to java.time (JSR-310).

Quoted from the Joda-Time homepage.

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