Working with Time Zones in Java 8 | ZonedDateTime, ZoneId tutorial with examples
Time Zone handling in Java 8 has improved with the new
To begin with, I will first show the individual classes which define a date-time instance with time zones via a diagram detailing how these classes interact. These individual classes from
Understanding the role of Java 8 Date/Time classes shown above
LocalDateTime:
Instant:
However, you may want to change the time zone of an Instant to something other than UTC for which
ZonedDateTime: As we saw above, on invoking the
ZoneId:
Zone IDs are of 3 main types -
ZoneRules:An instance of
All the rules specific to a time zone, such as conversions to/from that zone during 'day light saving', or during the transition times when the daylight saving is put in place or removed, etc are captured in
ZoneRulesProvider:
Scenario 1: Starting with a java.time.Instant value and converting to a desired time zone
OUTPUT of the above code
Explanation of the code
OUTPUT of the above code
Explanation of the code
Scenario 3: Converting ZonedDateTime to its equivalent in a different time zone
OUTPUT of the above code
Explanation of the code
java.time
package. However, to effectively use time zones in code one needs to understand certain fundamental components(or classes) that Java 8 has defined to capture all aspects of time zones. These aspects cover areas such as the standard UTC time, zone offsets, offset conversion rules (including rules around daylight saving - especially during the transition times twice a year) and the actual time zones themselves. The good news is that most of the aspects, such as daylight savings and time zone conversions, are already in-built in Java 8. All that one needs to learn is how to use these in-built classes as per specific requirement at hand.To begin with, I will first show the individual classes which define a date-time instance with time zones via a diagram detailing how these classes interact. These individual classes from
java.time
and java.time.zone
packages are the ones you will be using to get your application to work across time zones. Next, I will explain the roles that each of these classes plays individually. This will be followed by seeing practical commonly used scenarios showing how to actually incorporate time zones in your code. At the end of this tutorial, the reader should be able to understand the fundamentals around time zone handing in Java 8, and know exactly which class to pick(and which ones to ignore) as per their specific requirement.
Classes involved with Time Zones handling in Java 8
java.time.LocalDateTime
is strictly not a part of the set of classes responsible for time zones handling. However, it will be, in most likelihood, the class on top of which time zones will be added on majority of occasions (except those few cases where instances of java.time.Instant
are being used). Hence, its importance!LocalDateTime
contains a date and a time; a combination of a LocalDate
and a LocalTime
. The key aspect of LocalDateTime
is that the time is indeed "local", i.e. it belongs to a local time-line with no time zone associated with it. So, to make this time relevant in a global context we will need to add a time zone to it. This will be done using the LocalDateTime.atZone(ZoneId zoneId)
method. This method returns an instance of a ZonedDateTime
which contains the date and time along with time zone passed to it using zoneId
.Instant:
java.time.Instant
is the class encapsulating the time elapsed from the standard Java epoch(beginning of time in Java) of 1970-01-01T00:00:00Z. Instant
instances do have a time zone associated with them - UTC to be specific. So, an instance of Instant holds a value of date-time with a UTC time-line.However, you may want to change the time zone of an Instant to something other than UTC for which
Instant.atZone()
method comes in handy. Instant.atZone(ZoneId zoneId)
method returns a ZonedDateTime
instance with the time zone converted to the zoneId
passed as a parameter to the method.ZonedDateTime: As we saw above, on invoking the
atZone()
method of both LocalDateTime
and Instant
results in an instance of java.time.ZonedDateTime
being returned. When working with date-time objects with a time zone, ZonedDateTime
is what you must use as your primary class to hold the objects as well as to manipulate them as per your needs.ZoneId:
java.time.ZoneId
is the unique identifier of a time zone. As we saw above, converting both LocalDateTime
and an Instant
requires us to tell the exact 'zone ID' for the resulting ZonedDateTime
. Zone ID holds the time zone value which is equivalent to what we say in common parlance as "UTC-8:00" or "America/Los_Angeles" or "PST".Zone IDs are of 3 main types -
- ZoneOffset: These are normalized Zone Ids, denoted by "Z", and show time in ‘UTC+/-’ format. Example: ‘20:30Z’.
- Offset Style Zone Ids: These start with 'UTC', 'GMT' or 'UT' and show time with +/- prepended to them. Example: 'GMT+02:00'.
- Region Based Ids: These do not start with 'UTC', 'GMT', 'UT' '+' or '-', and are of minimum 2 characters. They have the format ‘{area}/{city}’. Example: "America/Los_Angeles". To reference a complete list of region based IDs supported in Java, please refer the table hereClick to see complete list of worldwide Region Based Zone IDs.
ZoneOffset
instances provide a standard way for working with time zones; which is perhaps the reason why java designers used ZoneOffset
as the standard time zone identifier for instances of java.time.Instant
. For example: An Instant
value would look like this - '2016-11-29T16:47:37.545Z' where 'Z' at the end indicates that a ZoneOffset
of 'UTC+00:00' is being used.ZoneRules:An instance of
java.time.zone.ZoneRules
encapsulates the rules for converting a given Date-Time to a specific ZoneId
. You can get the ZoneRules
for a ZoneId
by invoking ZoneId.getRules()
method on a ZoneId
instance.All the rules specific to a time zone, such as conversions to/from that zone during 'day light saving', or during the transition times when the daylight saving is put in place or removed, etc are captured in
ZoneRules
. The good news is that the specific rules for all the time zones in existence today in the IANA Time Zone Database (TZDB) have already been incorporated in java.time.zone.DefaultZoneRulesProvider
which is loaded by default.ZoneRulesProvider:
java.time.zone.ZoneRulesProvider
is responsible for configuring of time zone rules at Java platform-level or environment level. The ZoneRulesProvider
(s) to be used for a JVM instance can be declared via a configuration file or programmatically. However, for most common time zone uses the DefaultZoneRulesProvider
, mentioned earlier, will be sufficient.Changing time zones of a java.time.Instant instance
package com.javabrahman.java8.time;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
public class InstantTimeZoneHandling {
public static void main(String args[]) {
//Starting with an java.time.Instant value
Instant timeStamp= Instant.now();
System.out.println("Machine Time Now:" + timeStamp);
//timeStamp in zone - "America/Los_Angeles"
ZonedDateTime LAZone= timeStamp.atZone(ZoneId.of("America/Los_Angeles"));
System.out.println("In Los Angeles(America) Time Zone:"+ LAZone);
//timeStamp in zone - "GMT+01:00"
ZonedDateTime timestampAtGMTPlus1= timeStamp.atZone(ZoneId.of("GMT+01:00"));
System.out.println("In 'GMT+01:00' Time Zone:"+ timestampAtGMTPlus1);
}
}
Machine Time Now : 2016-11-29T14:23:25.551Z In 'Los Angeles(America)' Time Zone : 2016-11-29T06:23:25.551-08:00[America/Los_Angeles] In 'GMT+01:00' Time Zone : 2016-11-29T15:23:25.551+01:00[GMT+01:00]
InstantTimeZoneHandling
’smain()
method starts off with getting the current machine timestampRead quick coding tip on getting current machine timestamp using Instant.now() usingInstant.now()
and assigns it to a variable namedtimeStamp
.Instant
objects are by default in UTC time zone. Printing the value oftimestamp
gives us2016-11-29T14:23:25.551Z
. 'Z' here denotes theUTC+00:00
time zone.- We then use the
Instant.atZone()
method to converttimeStamp
’s time zone to the"America/Los Angeles"
time zone usingZoneId.of()
method like this -timeStamp.atZone(ZoneId.of("America/Los_Angeles"))
. ZoneId.of()
method returns a 'proper'ZoneId
instance which is standard in thejava.time
package. ThisZoneId
is then fed as input toatZone()
method.- The
atZone()
method returns aZonedDateTime
instance which containstimeStamp
’s time converted to its equivalent time in"America/Los_Angeles"
time zone which is2016-11-29T06:23:25.551-08:00[America/Los_Angeles]
, which is 8 hours behind UTC time. - Similarly, using the
"GMT+01:00"
time zone we get thetimeStamp
’s equivalent time in aZonedDateTime
instance which is2016-11-29T15:23:25.551+01:00[GMT+01:00]
Adding time zone to LocalDateTime
package com.javabrahman.java8.time;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
public class LocalDateTimeWithTimeZones {
public static void main(String args[]) {
//Starting with an java.time.LocalDateTime value of '2016-11-28T09:30'
LocalDateTime localDateTime= LocalDateTime.of(2016, 11, 28, 9, 30);
System.out.println("LocalDateTime is:"+ localDateTime);
//Adding "America/Los_Angeles" as the Time Zone to localDateTime
ZonedDateTime LAZonedDateTime= localDateTime.atZone(ZoneId.of("America/Los_Angeles"));
System.out.println("In Los Angeles(America) Time Zone:"+ LAZonedDateTime);
}
}
LocalDateTime is : 2016-11-28T09:30 In Los Angeles(America) Time Zone : 2016-11-28T09:30-08:00[America/Los_Angeles]
- The
main()
method ofLocalDateTimeWithTimeZones
class starts with defining aLocalDateTime
instance with value2016-11-28T09:30
using theLocalDateTime.of()
method. At this moment thelocalDateTime
variable does not have a time zone stored in it. - Next the time zone for
"America/Los_Angeles"
is added tolocalDateTime
instance by using theLocalDateTime.atZone()
method, which usesZoneId.of()
method similar to the way we saw in previous Scenario 1. - The
atZone()
method adds the"America/Los_Angeles"
time zone tolocalDateTime
and returns aZonedDateTime
instance namedLAZonedDateTime
. - The value of
LAZonedDateTime
is then printed as2016-11-28T09:30-08:00[America/Los_Angeles]
. The printed value shows that the time zone name[America/Los_Angeles]
and the offset from UTC '-08:00
' have indeed been added inLAZonedDateTime
. - Note - in the next Scenario 3, we will not write the code from scratch and use the
ZonedDateTime
variable -LAZonedDateTime
we have defined just now.
Converting ZonedDateTime to its equivalent in a different time zone
//LAZonedDateTime's equivalent in "UTC+00:00" Time Zone
ZonedDateTime LADateTimeToUTC= LAZonedDateTime.withZoneSameInstant(ZoneId.of("UTC+00:00"));
System.out.println("Converted to 'UTC' Time Zone:"+ LADateTimeToUTC);
//LAZonedDateTime's equivalent in "GMT+01:00" Time Zone
ZonedDateTime LADateTimeToGMTPlus1= LAZonedDateTime.withZoneSameInstant(ZoneId.of("GMT+01:00"));
System.out.println("Converted to 'GMT+01:00' Time Zone:"+ LADateTimeToGMTPlus1);
Converted to 'UTC' Time Zone : 2016-11-28T17:30Z[UTC] Converted to 'GMT+01:00' Time Zone : 2016-11-28T18:30+01:00[GMT+01:00]
- The above code snippet is in continuation of the code we saw in Scenario 2, with
LAZonedDateTime
containing the value2016-11-28T09:30-08:00[America/Los_Angeles]
. - First
LAZonedDateTime
is converted toUTC+00:00
time zone usingZonedDateTime.withZoneSameInstant()
method. ZonedDateTime.withZoneSameInstant()
method keeps the time stored inZonedDateTime
instance as the same and converts it to its equivalent in the required time zone passed as a parameter to it.This method returns back aZonedDateTime
instance with the changed time zone.- So,
2016-11-28T09:30-08:00[America/Los_Angeles]
is converted to its equivalent time inUTC+00:00
time zone which is2016-11-28T17:30Z[UTC]
. - Similarly, next
2016-11-28T09:30-08:00[America/Los_Angeles]
is converted to its equivalent time inGMT+01:00
time zone which is2016-11-28T17:30Z2016-11-28T18:30+01:00[GMT+01:00]
.
Tutorials on Java 8’s new Date and Time API
Overview of Java 8's new Date and Time APIClick to Read Overview of Java 8's new Date-Time API Working with time zones in Java 8| ZonedDateTime, ZoneId tutorial with examplesClick to Read tutorial on time zone handling in Java 8 How to convert LocalDate to String and String to LocalDateClick to Read tutorial on String to LocalDate conversions How to convert java.util.Date to java.time.LocalDateClick to Read tutorial on java.util.Date to LocalDate conversion Formatting localized dates in Spanish and FrenchClick to Read date formatting in Spanish & French How to get day-of-week for a given dateHow to get day-of-week using java.time.DayOfWeek enumDate Modification using TemporalAdjuster Click to Read Tutorial on TemporalAdjusters
Overview of Java 8's new Date and Time APIClick to Read Overview of Java 8's new Date-Time API Working with time zones in Java 8| ZonedDateTime, ZoneId tutorial with examplesClick to Read tutorial on time zone handling in Java 8 How to convert LocalDate to String and String to LocalDateClick to Read tutorial on String to LocalDate conversions How to convert java.util.Date to java.time.LocalDateClick to Read tutorial on java.util.Date to LocalDate conversion Formatting localized dates in Spanish and FrenchClick to Read date formatting in Spanish & French How to get day-of-week for a given dateHow to get day-of-week using java.time.DayOfWeek enumDate Modification using TemporalAdjuster Click to Read Tutorial on TemporalAdjusters