The Answer by Richters is correct and should be accepted.
As Richters noted, there is no logic to Daylight Saving Time (DST) or other anomalies. Politicians arbitrarily redefine the offset-from-UTC used in their time zones. They make these changes often with little forewarning, or even no warning at all as North Korea did a few weeks ago.
java.time
Here are some further thoughts, and example code using the modern java.time classes that succeeded the Joda-Time classes shown in his Answer.
These changes are tracked in a list maintained by ICANN, known as tzdata, formerly known as the Olson Database. Your Java implementation, host operating system, and database system likely all have their own copies of this data which must be replaced as needed when changes are mode to zones you care about. There is no logic to these changes, so there is no way to predict the changes programmatically. Your code must call upon a fresh copy of tzdata.
So for example between the 25th and the 31th of October we have to check, if the actual date is a sunday, it is before or after 2 o'clock...
Actually, you need not determine the point of the cut-over. A good date-time library handles that for you automatically.
Java has the best such library, the industry-leading java.time classes. When you ask for a time-of-day on a certain date in a certain region (time zone), if that time-of-day is no valid an adjustment is made automatically. Read the documentation for the ZonedDateTime
to understand the algorithm used in that adjustment.
ZoneId z = ZoneId.of( "America/Montreal" );
LocalDate ld = LocalDate.of( 2018 , Month.MARCH , 11 ); // 2018-03-11.
LocalTime lt = LocalTime.of( 2 , 0 ); // 2 AM.
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z );
Notice the result is 3 AM rather than the 2 AM requested. There was no 2 AM on that date in that zone. So java.time adjusted to 3 AM as the clock “Springs ahead” an hour.
zdt.toString(): 2018-03-11T03:00-04:00[America/Montreal]
If you feel the need to investigate the rules defined for a time zone, use the ZoneRules
class.
Get the amount of DST shift used in the present moment.
Duration d = z.getRules().getDaylightSavings( Instant.now() ) ;
Get the next planned change, represented as a ZoneOffsetTransition
object.
ZoneId z = ZoneId.of( "America/Montreal" );
ZoneOffsetTransition t = z.getRules().nextTransition( Instant.now() );
String output = "For zone: " + z + ", on " + t.getDateTimeBefore() + " duration change: " + t.getDuration() + " to " + t.getDateTimeAfter();
For zone: America/Montreal, on 2018-11-04T02:00 duration change: PT-1H to 2018-11-04T01:00
Specify a proper time zone name in the format of continent/region
, such as America/Montreal
, Africa/Casablanca
, or Pacific/Auckland
. Never use the 3-4 letter abbreviation such as EST
or IST
as they are not true time zones, not standardized, and not even unique(!).
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date
, Calendar
, & SimpleDateFormat
.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.*
classes.
Where to obtain the java.time classes?
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval
, YearWeek
, YearQuarter
, and more.