19 December 2012

Date and Time in Java 8 (2)

This is the second part of a series on JSR-310; Part 1: The Basics. It's been translated into Serbo-Croatian here.


The Local* classes that we looked at last time all ignored the complexity introduced by timezones. A timezone is a set of rules, corresponding to a region where the standard time is the same, there are about 40 of them. Each timezone has an offset from UTC, so it's time moves in sync with UTC but by some difference. Unfortunately the defined offset from UTC can vary due to changes in the rules. Timezones have two identifiers: abbreviated, eg "PLT", and longer, eg: "Asia/Karachi".

A time-zone offset is the period of time that a time-zone differs from Greenwich/UTC. Offsets can be resolved from a timezone at a particular point in time. For example in summer Paris is Greenwich/UTC + one hour. In winter it's Greenwich/UTC + two hours. You don't need to be aware of all the details, since JSR-310 abstracts these away for you, but you do need to understand the basic concept that there isn't a one-to-one mapping between offsets and timezones. When designing your application you should consider what scenarios are appropriate for using timezones and when offsets are appropriate.

Timezone Classes

There are a number of classes representing parts of the timezone system. These classes are all field-based classes, which is to say they can be queried for subfields, such as a Day, a Second or a ZoneOffset.

There are also classes for modelling specific concepts within the domain of TimeZones:


The API conventions that were outlined for Local* classes are also present in the field based timezone classes. These include:

Object creation using factory methods starting with 'of', 'from' or 'now'.

// You can specify the zone id when creating a zoned date time
ZoneId id = ZoneId.of("Europe/Paris");
ZonedDateTime zoned = ZonedDateTime.of(dateTime, id);

zoned = ZonedDateTime.parse("2007-12-03T10:15:30+01:00[Europe/Paris]");

ZoneOffset offset = ZoneOffset.of("+2:00");

// Extract useful components

OffsetTime time = OffsetTime.now();

Values accessed by get* methods, and new objects created by calling with* or plus* methods on an existing object.

// changes offset, whilst keeping the same point on the timeline
OffsetTime sameTimeDifferentOffset = time.withOffsetSameInstant(offset);

// changes the offset, and updates the point on the timeline
OffsetTime changeTimeWithNewOffset = time.withOffsetSameLocal(offset);

// Can also create new object with altered fields as before

A well defined ordering comparison based on the timeline.

A powerful Adjuster mechanism in order to model business logic based manipulations.

ZonedDateTime zdt;

zdt = zoned.with(firstDayOfYear());
zdt = zoned.with(lastInMonth(TUESDAY));
zdt = zoned.with(time);

Databases and JDBC

ANSI SQL provides two types that are related to timezones - the misleading named "TIME WITH TIME ZONE" and "TIMESTAMP WITH TIME ZONE". Neither of these types actually store a timezone! They both store the offset. This is important because it means that you can't resolve the exact timezone after persistence. This means developers need to consider whether the appropriate choice is to store just the offset or whether they should also store the timezone as well.

It's worth noting that there will no public JDBC API changes in order to support JSR-310, merely to the spec. The existing generic setObject and getObject methods will be sufficient.

Existing Timezone classes

There is an existing timezone class in Java - java.util.TimeZone - but this isn't used by JSR-310 since all 310 classes are immutable, and timezone is mutable. There are also subtle incompatible issues to be aware of, specifically that the previous timezone implementation only uses 32bit data for storing timezones. This limits the supported values to between 1901-12-13T20:45:52Z and 2038-01-19T03:14:07Z. Obviously JSR-310 isn't limited by the restriction, and supports a wider range of timezones. The result is that outside of the aforementioned dates compatibility between the existing timezone classes and JSR-310 isn't guaranteed, but if you always use the new classes they will provide the correct timezone information for a wider range of dates than was previously possible.


I've looked at how timezones can be used, and when to consider OffsetDateTime and ZonedDateTime. In Part 3 I plan to talk about Periods, which are a way of representing the different between two dates or times.

You can follow the final stages of JSR-310 development by reading the mailing list or on the openjdk project, where the implementation work is being done and commits get emailed

Read More: Date and Time in Java 8 (1)