The Answer by Andreas is spot-on correct.
Example Code
Let's test it with some code. DST in the United States & Canada expires this year at 02:00 on November 1, 2015.
Let‘s start with 1 AM in “local” date-time, meaning not tied to the timeline and ignoring the issue of time zones. Add an hour, and we get 2 AM. Makes sense.
LocalDateTime localDateTime = LocalDateTime.of( 2015 , Month.NOVEMBER , 1 , 1 , 0 ); // 1 AM anywhere. Not tied the timeline nor to any time zone.
LocalDateTime localDateTimeOneHourLater = localDateTime.plusHours( 1 ); // 2 AM anywhere, in no particular time zone, ignoring DST.
Next we get specific, with a particular time zone. We take that 1 AM anywhere and put it into the time zone of America/Los_Angeles
(west coast of United States).
ZoneId zoneId_LosAngeles = ZoneId.of( "America/Los_Angeles" );
ZonedDateTime before = localDateTime.atZone( zoneId_LosAngeles ); // Assign a time zone, tying this vague date-time idea/generality to an actual moment on the time line.
Now add an hour, and see what we get. If DST is ignored, we’ll get 2 AM. If DST is respected, we’ll get 1 AM… when reaching 2 AM the wall-clock time jumps back to 1 AM but with a new offset-from-UTC. This is colloquially known as "fall back" in the fall (autumn).
ZonedDateTime after = before.plusHours( 1 ); // 2 AM? Nope, 1 AM because DST Daylight Saving Time expires at 2 AM Nov 1, 2015.
Dump to console.
System.out.println( "localDateTime : " + localDateTime );
System.out.println( "localDateTimeOneHourLater : " + localDateTimeOneHourLater );
System.out.println( "before : " + before );
System.out.println( "after : " + after );
When run, we get this output. Without a time zone, 1 AM + 1 hour = 2 AM. Remember these are "local" date-time values, not UTC. They represent only the vague idea of a date-time, not an actual moment on the timeline.
localDateTime : 2015-11-01T01:00
localDateTimeOneHourLater : 2015-11-01T02:00
But with time zones applied on the day DST expires, we get different results. Note how the time-of-day remains 01:00
but the offset-from-UTC changes from -07:00
to -08:00
.
before : 2015-11-01T01:00-07:00[America/Los_Angeles]
after : 2015-11-01T01:00-08:00[America/Los_Angeles]
Perhaps this would more clear and easier to verify if we adjust into UTC. We can do that simply by accessing the before
and after
objects as Instant
objects. The System.out.println
then implicitly calls the toString
method.
System.out.println( "before.toInstant : " + before.toInstant() );
System.out.println( "after.toInstant : " + after.toInstant() );
When run.
before.toInstant : 2015-11-01T08:00:00Z
after.toInstant : 2015-11-01T09:00:00Z

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.