Java 101: Catching up with the Java Date and Time API

Get to know the java.time classes you're most likely to use in Java 8

Page 7 of 7

ZoneId, ZoneOffset, ZonedDateTime, and OffsetDateTime

A time zone is a region of the Earth's surface in which all localities have the same standard time. Each time zone has an identifier (such as Europe/Paris) and an offset from UTC/Greenwich (such as +01:00) that changes where daylight savings time is observed and is in effect.

The java.time package provides ZoneId, ZoneOffset, ZonedDateTime, and OffsetDateTime classes for working with time zones:

  • ZoneId describes a time-zone identifier and provides rules for converting between an Instant and a LocalDateTime.
  • ZoneOffset describes a time-zone offset, which is the amount of time (typically in hours) by which a time zone differs from UTC/Greenwich.
  • ZonedDateTime describes a date-time with a time zone in the ISO-8601 calendar system (such as 2007-12-03T10:15:30+01:00 Europe/Paris).
  • OffsetDateTime describes a date-time with an offset from UTC/Greenwich in the ISO-8601 calendar system (such as 2007-12-03T10:15:30+01:00).

ZonedDateTime and OffsetDateTime are similar in that they both have offsets from UTC/Greenwich. However, ZonedDateTime also identifies the time zone whose rules are used to handle ambiguous local date-times.

For example, suppose you moved the clock back one hour from 2 a.m. to 1 a.m. at the end of daylight savings time. In this case, 1:30 a.m. would occur twice, causing an ambiguity. OffsetDateTime doesn't account for this case but ZonedDateTime does.

Use cases for time zone classes

You could use ZonedDateTime to represent a date and time without relying on a specific server context. You could use OffsetDateTime to serialize data to a database and as the serialization format for logging timestamps when working with servers in different time zones.

Time zone classes: A demo

Like the previously discussed classes, java.time's time-zone classes use fluent factory methods to obtain instances. They also support getters and adjusters. Listing 7 demonstrates class instantiation, getters, and adjusters.

Listing 7. HumanTimeDemo.java (version 4)

import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZonedDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;

import java.time.temporal.Adjusters;

public class HumanTimeDemo
{
   public static void main(String[] args)
   {
      ZoneId zid = ZoneId.systemDefault();
      System.out.printf("Zone Id = %s%n", zid);
      System.out.printf("Rules = %s%n", zid.getRules());
      System.out.printf("DST in effect: %b%n",
                        zid.getRules().isDaylightSavings(Instant.now()));

      zid = ZoneId.of("Europe/Paris");
      System.out.printf("Zone Id = %s%n", zid);

      ZoneOffset zoffset = ZoneOffset.of("+06:00");
      System.out.printf("Zone Offset = %s%n", zoffset);
      System.out.printf("Total seconds = %d%n", zoffset.getTotalSeconds());

      ZonedDateTime zonedDateTime = ZonedDateTime.now();
      System.out.printf("Zoned date and time = %s%n", zonedDateTime);
      System.out.printf("Zone = %s%n", zonedDateTime.getZone());

      zoffset = ZoneOffset.from(zonedDateTime);
      System.out.printf("Zone Offset = %s%n", zoffset);
 
      OffsetDateTime offsetDateTime = OffsetDateTime.now();
      System.out.printf("Offset date and time = %s%n", offsetDateTime);
      System.out.printf("Offset date and time = %s%n", 
                        offsetDateTime.with(Adjusters.lastDayOfMonth()));

      zonedDateTime = ZonedDateTime.of(2013, 11, 2, 3, 00, 0, 0, 
                                       ZoneId.of("America/Chicago"));
      System.out.printf("Zoned date and time = %s%n", zonedDateTime);


      zonedDateTime = ZonedDateTime.of(2013, 11, 3, 3, 00, 0, 0, 
                                       ZoneId.of("America/Chicago"));
      System.out.printf("Zoned date and time = %s%n", zonedDateTime);

      offsetDateTime = OffsetDateTime.of(2013, 11, 2, 3, 00, 0, 0, zoffset);
      System.out.printf("Offset date and time = %s%n", offsetDateTime);

      offsetDateTime = OffsetDateTime.of(2013, 11, 3, 3, 00, 0, 0, zoffset);
      System.out.printf("Offset date and time = %s%n", offsetDateTime);
   }
}

The main() method in Listing 7 is fairly easy to follow and proves that the new Java time-zone classes aren't hard to use. For example, you can easily determine if the current instant lies in daylight savings time (DST) for a specific zone ID.

The final part of the main() method demonstrates the difference between ZonedDateTime and OffsetDateTime in my time zone. For each class, I obtained an instance that reflected 3 a.m. on November 2, 2013 and November 3, 2013. (DST ends in my time zone at 2 a.m. on November 3.)

At the time of this writing, DST is in effect and the offset is -05:00. ZonedDateTime will change this offset to -06:00 when DST ends. However, OffsetDateTime will not change the offset because it has no access to time zone rules, so it's unable to find out when DST ends.

Compile Listing 7 and run the application. Your output should be similar to what's below:

Zone Id = America/Chicago
Rules = ZoneRules[currentStandardOffset=-06:00]
DST in effect: true
Zone Id = Europe/Paris
Zone Offset = +06:00
Total seconds = 21600
Zoned date and time = 2013-03-23T19:37:03.042-05:00[America/Chicago]
Zone = America/Chicago
Zone Offset = -05:00
Offset date and time = 2013-03-23T19:37:03.104-05:00
Offset date and time = 2013-03-31T19:37:03.104-05:00
Zoned date and time = 2013-11-02T03:00-05:00[America/Chicago]
Zoned date and time = 2013-11-03T03:00-06:00[America/Chicago]
Offset date and time = 2013-11-02T03:00-05:00
Offset date and time = 2013-11-03T03:00-05:00

In conclusion

The new Java Date and Time API overcomes various problems with Java's previous date and time APIs, and is organized into the main java.time package and its four subpackages. Although you'll most commonly use java.time's Instant, Duration, LocalDate, LocalTime, LocalDateTime, ZoneId, ZoneOffset, ZonedDateTime, and OffsetDateTime classes, there are other types to consider. Check out the exercises in this article's code source file to learn more about the Java Date and Time API.

Jeff Friesen is a freelance tutor and software developer with an emphasis on Java and Android. In addition to writing Java and Android books for Apress, Jeff has written numerous articles on Java and other technologies for JavaWorld, informIT, Java.net, and DevSource. Jeff can be contacted via his website at TutorTutor.ca.

Learn more about this topic

Recommended

  • "All I want for Java 8 ..." (Dusting Marx, April 2011): A developer's annotated wish list for Java 8.
  • "How badly do we want a new Java Date and Time API?" (Dustin Marx, March 2012) surveys developer opinion about the Java date and time infrastructure prior to Java 8.
  • JavaWorld syndicated blogger Ted Neward explains why he believes that Java 8 will be a game changer for Java development.
  • Martin Fowler discusses precision in his blog post about Time Point implementation in computer programming (MartinFowler.com, March 2004).

More about the Java Date and Time API

  • JSR 310: Date and Time API: The specification is the definitive source for learning about the new types in java.time.
  • Also visit the OpenJDK Project ThreeTen homepage, which includes a link to JSR 310's Sourceforge repository and a current release timeline.
  • JSR 310 co-lead and Joda Time creator Stephen Colebourne has written extensively on his blog about the relationship between Joda Time and the new Java Date and Time APIs.
  • In "From Instants to Eras, the Future of Java" (JW Blogs, October 2012) Dustin Marx reports from JavaOne 2012 on the potential impact of the new Date and Time API, as well as some of its core concepts.

Popular articles in the Java 101 series

| 1 2 3 4 5 6 7 Page 7