30

I am thinking of using the new java 8 Date Time API. I googled a bit and found jodaTime as good choice for java but still kind of interested to see how this new API works.

I am storing all time in UTC values in my datastore and will be converting them to Local Time Zone specific value based on user's timezone. I can find many articles showing how to use new Java Date Time API. However I am not sure if the API will take care of DST changes ? Or do we have any better way of handling Date ?

I am just learning the new Date API , so thought of hearing your thoughts on handling the DateTime and displaying it on the basis of Users TimeZone.

Raja
  • 627
  • 1
  • 9
  • 24
  • 3
    In short: yes, DST is taken care of. Java 8 date-time API was created based on Joda time. – Mick Mnemonic Sep 29 '15 at 01:04
  • 2
    @Raja I'll correct your terms to prevent confusion… "Local" in date-time work means "for any locality", as in "Christmas starts at midnight December 25, 2015". Such a local date-time has no time zone. Indeed, it has no real meaning until you adjust it into a specific time zone. Midnight on the 25th comes earlier in Paris than in Montréal. So, in common business apps we rarely use "Local". You will be taking your stored date-time values from your database, working with them in your business logic in UTC generally, and adjusting to a `ZonedDateTime` only for presentation to a user. – Basil Bourque Sep 29 '15 at 01:46

3 Answers3

46

It depends on which class you use:

  • Instant is an instantaneous point on the global time-line (UTC), and is unrelated to time-zone.
  • LocalDate and LocalDateTime have no concept of time-zone, but calling now() will of course give you your correct time.
  • OffsetDateTime has a time-zone, but doesn't support Daylight Savings Time.
  • ZonedDateTime has full time-zone support.

Converting between them usually requires a time-zone, so to answer your question:

    Yes, Java 8 Date/Time can take care of DST, if you use it right.

Andreas
  • 154,647
  • 11
  • 152
  • 247
  • thanks for mentioning that `OffsetDateTime` doesn't support DST, that's precisely what I needed, thanks! – Clint Eastwood Jan 11 '18 at 22:15
  • `localDateTime.atZone( zoneId_LosAngeles );` <--- So localDateTime accepts zone; then why this answer says `LocalDateTime have no concept of time-zone`? – Kanagavelu Sugumar Oct 01 '20 at 05:31
  • 2
    @KanagaveluSugumar Because a `LocalDateTime` object has no concept of which time zone the date/time value it embeds belongs to. Just because the class supplies a *helper method* for converting the stored value to an object of a different type, doesn't mean that the object and its data knows anything about time zones. The `localDateTime.atZone(zoneId)` method is a *convenience method*, making it simpler to call than `ZonedDateTime.of(localDateTime, zoneId)`, which is exactly what it does for you, as you can see if you *look at the source code* of the method. – Andreas Oct 04 '20 at 04:24
43

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

Table of date-time types in Java, both modern and legacy


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.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • Thanks for your contributions... I've noticed that you have quite a strong acumen with the Date/Time API's... :) – Edward J Beckett Apr 15 '19 at 21:57
  • Great. I thought I'll have to do the daylight saving time conversion manually by adding an hour or using different timezone but java does it already for us. Thanks a lot – iAmLearning May 18 '21 at 09:16
5

Yes, the Java API will take DST changes into account.

This tutorial explains quite well how to convert dates between timezones and how to choose the right class to represent a date: https://docs.oracle.com/javase/tutorial/datetime/iso/timezones.html

You can also look at this class which represents the rules for each zone: http://docs.oracle.com/javase/8/docs/api/java/time/zone/ZoneRules.html

In particular, this method can tell you if a particular instant is in daylight savings: http://docs.oracle.com/javase/8/docs/api/java/time/zone/ZoneRules.html#isDaylightSavings-java.time.Instant-

eugenioy
  • 11,825
  • 28
  • 35
  • Thanks for reminding the value of Orcale docs :) Those links are more helpful to me. – Raja Sep 29 '15 at 01:23