Java 8 Time Zone and Offset Classes with Examples

In this guide, we will discuss the Java 8 Time Zone and Offset Classes with Examples.
A time zone is a region of the earth where the same standard time is used. Each time zone is described by an identifier and usually has the format region/city (Asia/Tokyo) and an offset from Greenwich/UTC time. For example, the offset for Tokyo is +09:00.
Examples of this guide are available on Github.
The Date-Time API provides two classes for specifying a time zone or an offset:
  • ZoneId 
  • ZoneOffset
The Date-Time API provides three temporal-based classes that work with time zones:
  • ZonedDateTime
  • OffsetDateTime
  • OffsetTime
Let's discuss each class with examples.

1. ZoneId and ZoneOffset

The Date-Time API provides two classes for specifying a time zone or an offset:
  • ZoneId - specifies a time zone identifier and provides rules for converting between an Instant and a LocalDateTime.
  • ZoneOffset - specifies a time zone offset from Greenwich/UTC time.

1.1 ZoneId and ZoneOffset Class Examples

The following code, from the TimeZoneId class example, prints a list of all time zones that use offsets from Greenwich/UTC that are not defined in whole hours.

Example: Program to demonstrate ZoneId and ZoneOffset classes. 
package com.ramesh.java8.datetime;

import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;

public class TimeZoneId {
 public static void main(String[] args) {

  // Get the set of all time zone IDs.
  Set<String> allZones = ZoneId.getAvailableZoneIds();

  // Create a List using the set of zones and sort it.
  List<String> zoneList = new ArrayList<String>(allZones);
  Collections.sort(zoneList);

  LocalDateTime dt = LocalDateTime.now();

  Path p = Paths.get("timeZones");
  try (BufferedWriter tzfile = Files.newBufferedWriter(p, StandardCharsets.US_ASCII)) {
   for (String s : zoneList) {
    ZoneId zone = ZoneId.of(s);
    ZonedDateTime zdt = dt.atZone(zone);
    ZoneOffset offset = zdt.getOffset();
    int secondsOfHour = offset.getTotalSeconds() % (60 * 60);
    String out = String.format("%35s %10s%n", zone, offset);

    // Write only time zones that do not have a whole hour offset
    // to standard out.
    if (secondsOfHour != 0) {
     System.out.printf(out);
    }

    // Write all time zones to the file.
    tzfile.write(out);
   }
  } catch (IOException x) {
   System.err.format("IOException: %s%n", x);
  }
 }
}
Output:
                   America/St_Johns     -02:30
                      Asia/Calcutta     +05:30
                       Asia/Colombo     +05:30
                         Asia/Kabul     +04:30
                     Asia/Kathmandu     +05:45
                      Asia/Katmandu     +05:45
                       Asia/Kolkata     +05:30
                     Asia/Pyongyang     +08:30
                       Asia/Rangoon     +06:30
                        Asia/Tehran     +04:30
                        Asia/Yangon     +06:30
                 Australia/Adelaide     +09:30
              Australia/Broken_Hill     +09:30
                   Australia/Darwin     +09:30
                    Australia/Eucla     +08:45
                      Australia/LHI     +10:30
                Australia/Lord_Howe     +10:30
                    Australia/North     +09:30
                    Australia/South     +09:30
               Australia/Yancowinna     +09:30
                Canada/Newfoundland     -02:30
                       Indian/Cocos     +06:30
                               Iran     +04:30
                            NZ-CHAT     +12:45
                    Pacific/Chatham     +12:45
                  Pacific/Marquesas     -09:30
The Date-Time API provides three temporal-based classes that work with time zones:
  • ZonedDateTime - handles a date and time with a corresponding time zone with a time zone offset from Greenwich/UTC. 
  • OffsetDateTime - handles a date and time with a corresponding time zone offset from Greenwich/UTC, without a time zone ID. 
  • OffsetTime - handles time with a corresponding time zone offset from Greenwich/UTC, without a time zone ID.
Let's discuss of these classes in detail with an example.

2. ZonedDateTime

  • The ZonedDateTime class combines the LocalDateTime class with the ZoneId class. 
  • It is used to represent a full date (year, month, day) and time (hour, minute, second, nanosecond) with a time zone (region/city, such as Europe/Paris).

2.1 ZonedDateTime Class Examples

The following code, from the Flight example, defines the departure time for a flight from San Francisco to Tokyo as a ZonedDateTime in the America/Los Angeles time zone. 
The withZoneSameInstant and plusMinutes methods are used to create an instance of ZonedDateTime that represents the projected arrival time in Tokyo, after the 650 minute flight. The ZoneRules.isDaylightSavings method determines whether it is daylight saving time when the flight arrives in Tokyo.
package com.ramesh.java8.datetime;

import java.time.DateTimeException;
import java.time.LocalDateTime;
import java.time.Month;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
/*
 * This example uses ZonedDateTime to calculate the arrival time of
 * a flight that leaves from San Francisco and arrives in Tokyo.
 * The flight is 10 hours, 50 minutes long. Formatters are used to
 * print the departure and arrival times.
 */

public class FlightZoneDateTimeExample {
    public static void main(String[] args) {
        DateTimeFormatter format = DateTimeFormatter.ofPattern("MMM d yyyy  hh:mm a");

        // Leaving from San Francisco on July 20, 2013, at 7:30 p.m.
        LocalDateTime leaving = LocalDateTime.of(2013, Month.JULY, 20, 19, 30);
        ZoneId leavingZone = ZoneId.of("America/Los_Angeles"); 
        ZonedDateTime departure = ZonedDateTime.of(leaving, leavingZone);

        try {
            String out1 = departure.format(format);
            System.out.printf("LEAVING:  %s (%s)%n", out1, leavingZone);
        } catch (DateTimeException exc) {
            System.out.printf("%s can't be formatted!%n", departure);
            throw exc;
        }

        // Flight is 10 hours and 50 minutes, or 650 minutes
        ZoneId arrivingZone = ZoneId.of("Asia/Tokyo"); 
        ZonedDateTime arrival = departure.withZoneSameInstant(arrivingZone)
                                         .plusMinutes(650);

        try {
            String out2 = arrival.format(format);
            System.out.printf("ARRIVING: %s (%s)%n", out2, arrivingZone);
        } catch (DateTimeException exc) {
            System.out.printf("%s can't be formatted!%n", arrival);
            throw exc;
        }

        if (arrivingZone.getRules().isDaylightSavings(arrival.toInstant())) 
            System.out.printf("  (%s daylight saving time will be in effect.)%n",
                              arrivingZone);
        else
            System.out.printf("  (%s standard time will be in effect.)%n",
                              arrivingZone);
    }
}
Output:
LEAVING:  Jul 20 2013  07:30 PM (America/Los_Angeles)
ARRIVING: Jul 21 2013  10:20 PM (Asia/Tokyo)
(Asia/Tokyo standard time will be in effect.)

3. OffsetDateTime

  • The OffsetDateTime class, in effect, combines the LocalDateTime class with the ZoneOffset class. 
  • It is used to represent a full date (year, month, day) and time (hour, minute, second, nanosecond) with an offset from Greenwich/UTC time (+/-hours:minutes, such as +06:00 or -08:00).

3.1 OffsetDateTime Class Examples

The following example uses OffsetDateTime with the TemporalAdjuster.lastDay method to find the last Thursday in July 2013.
// Find the last Thursday in July 2013.
LocalDateTime localDate = LocalDateTime.of(2013, Month.JULY, 20, 19, 30);
ZoneOffset offset = ZoneOffset.of("-08:00");

OffsetDateTime offsetDate = OffsetDateTime.of(localDate, offset);
OffsetDateTime lastThursday =
        offsetDate.with(TemporalAdjusters.lastInMonth(DayOfWeek.THURSDAY));
System.out.printf("The last Thursday in July 2013 is the %sth.%n",
                   lastThursday.getDayOfMonth());
Output:
The last Thursday in July 2013 is the 25th.

4. OffsetTime

  • The OffsetTime class, in effect, combines the LocalTime class with the ZoneOffset class.
  • It is used to represent time (hour, minute, second, nanosecond) with an offset from Greenwich/UTC time (+/-hours:minutes, such as +06:00 or -08:00).
  • The OffsetTime class is used in the same situations as the OffsetDateTime class, but when tracking the date is not needed.

Comments