In Joda Time, one can easily use the DateTimeZone.isLocalDateTimeGap
method to tell if a local date and time is invalid because it falls into the gap created by a spring-forward daylight saving time transition.
DateTimeZone zone = DateTimeZone.forID("America/New_York");
LocalDateTime ldt = new LocalDateTime(2013, 3, 10, 2, 0);
boolean inGap = zone.isLocalDateTimeGap(ldt); // true
But how do you detect the fall-back transition? In other words, if a local date and time could be ambiguous because there is an overlap, how do you detect that? I would expect something like zone.isLocalDateTimeOverlap
, but it doesn't exist. If it did, I would use it like so:
DateTimeZone zone = DateTimeZone.forID("America/New_York");
LocalDateTime ldt = new LocalDateTime(2013, 11, 3, 1, 0);
boolean overlaps = zone.isLocalDateTimeOverlap(ldt); // true
The Joda-Time documentation is clear that if there is an overlap during conversions, it will take the earlier possibility unless told otherwise. But it doesn't say how to detect that behavior.
The right way to handle DST in Java is to instantiate a Timezone with a specific TZDB Timezone ID, eg. “Europe/Rome”. Then, we'll use this in conjunction with time-specific classes like java.util.Calendar to get a proper configuration of the TimeZone's raw offset (to the GMT time zone), and automatic DST shift adjustments.
When there is no option to inject time provider or refactoring the whole class is no worth it, you may decide to use helper methods from Joda Time to achieve testable time-based code: With Joda Time we can use static method setCurrentTimeMillisFixed (), which will tell Joda objects to always return given value. According to documentation:
Note: Some governments, most notably Ireland, define daylight saving by describing a "standard" time in summer and a negative DST offset in winter. Joda-Time, like the JDK, follows a model for time-zone data where there is a raw offset all year round and a positive additional offset.
To use Joda Time Java library in the Gradle build project, add the following dependency into the build.gradle file. To use Joda Time Java library in the Maven build project, add the following dependency into the pom.xml file. To download the Joda Time .jar file you can visit Joda Time releases page at github.com/JodaOrg/joda-time
Take advantage of withEarlierOffsetAtOverlap()
public static boolean isInOverlap(LocalDateTime ldt, DateTimeZone dtz) {
DateTime dt1 = ldt.toDateTime(dtz).withEarlierOffsetAtOverlap();
DateTime dt2 = dt1.withLaterOffsetAtOverlap();
return dt1.getMillis() != dt2.getMillis();
}
public static void test() {
// CET DST rolls back at 2011-10-30 2:59:59 (+02) to 2011-10-30 2:00:00 (+01)
final DateTimeZone dtz = DateTimeZone.forID("CET");
LocalDateTime ldt1 = new LocalDateTime(2011,10,30,1,50,0,0); // not in overlap
LocalDateTime ldt2 = new LocalDateTime(2011,10,30,2,50,0,0); // in overlap
System.out.println(ldt1 + " is in overlap? " + isInOverlap(ldt1, dtz));
System.out.println(ldt2 + " is in overlap? " + isInOverlap(ldt2, dtz));
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With