Menu

User_Guide

Stephen Colebourne

This document is an initial user guide for the ThreeTen project and JSR 310.

Project goals

The primary goal of this project, via JSR-310, is to develop a new API to replace the

Date

and

Calendar

classes in the current Java SE platform. A key part of this is providing a new API that is dramatically easier to use and less error prone. As such, all the key public classes are immuatble and thread-safe.

A secondary goal is to define terminology and behaviour that other areas in computing can adopt.

Machine time-line

A time-line is a way of defining time progressing from the past to the future. The machine time-line is a mechanism of describing that is intended for machines to use. This is normally defined as a single incrementing number. For example, the millisecond count from 1970-01-01 in the

Date

class.

ThreeTen defines two core classes in this area.

The

Instant

class represents an instant in time to an accuracy of nanoseconds. It should be viewed as a replacement for java.util.Date. Operations on an Instant include comparison to another Instant and adding or subtracting a duration. The

Duration

class represents a duration of time to an accuracy of nanoseconds. There is no current JDK class representing this concept. Operations on a Duration include comparison to another Duration and mathematical operations like addition, subtraction, multiplication and division.

Time scales

The

Instant

class operates on a simplified time-line model that avoids dealing with leap seconds. It does this using the UTC-SLS convention which smooths leap seconds ensuring that there are always 60 seconds in a minute. These simplifications are useful because most applications do not take into account the existence of leap seconds. If your application needs to take them into account then an alternate class is needed. The

UTCInstant

class represents an instant taking into account the correct definition of UTC with leap seconds. The

TAIInstant

class represents a pure scientific time-scale.

Human time-line

The human time-line is a mechanism of describing that is intended for humans to use. This is defined as date-time fields, such as year month, day, hour, minute and second.

ThreeTen defines many classes in this area.

The

LocalDate

class represents a date. There is no representation of a time or time-zone. Methods are provided to get the year, month, day-of-month, day-of-week and day-of-year, and to return a new instance with any of these altered. Further methods allow a period of time measured in years, months or days to be added/subtracted.

 LocalDate date = LocalDate.of(2010, MonthOfYear.FEBRUARY, 26);
 date = date.plusDays(3);
 String str = date.toString();  // 2010-03-01

The

LocalTime

class represents a time. There is no representation of a date or time-zone. Methods are provided to get the hour, minute, second and nanosecond, and to return a new instance with any of these altered. Further methods allow a period of time measured in hours, minutes, seconds or nanoseconds to be added/subtracted.

 LocalTime time = LocalTime.of(12, 30);
 time = time.plusHours(3);
 String str = time.toString();  // 15:30

The

LocalDateTime

class represents a date-time. There is no representation of a time-zone. This is a combination of a

LocalDate

and a

LocalTime

and has similar methods.

 LocalDateTime dt = LocalDate.of(2010, MonthOfYear.FEBRUARY, 26, 12, 30);
 dt = dt.plusDays(3).plusHours(3);
 String str = dt.toString();  // 2010-03-01T15:30

The

OffsetDate

,

OffsetTime

and

OffsetDateTime

classes represents a date, time or date-time with a time-zone offset, such as +02:00. There is no representation of time-zone, as in Europe/Paris. These classes are built around the matching "Local" class and store the additional ZoneOffset instance.

OffsetDateTime

can be converted to and from an

Instant

with no loss of accuracy. The

ZonedDateTime

class represents a date-time with full time-zone rule, such as Europe/Paris. The addition of time-zone rules makes the class significantly more complex than

OffsetDateTime

as there are points on the local time-line that don't exist or exist twice (due to daylight savings time changes). This class handles those gaps and overlaps using the

ZoneResolver

class, with standard implementations in

ZoneResolvers

. Other representations of date and time include

Year

, representing a year,

YearMonth

, representing the combination of a year and a month,

MonthDay

, representing the combination of a month and a day, and

DateTimeFields

, representing any combination of date-time fields.

Periods

The period classes represent durations measured in human-scale units.

The

Period

class allows a period in years, months, days, hours, minutes and seconds to be stored. This is the most commonly used period class. There are two more advanced classes. The

PeriodField

class represents a period in a single unit, such as "6 Months". The

PeriodFields

class represents a compound period built of a collection of fields. Methods are provided to allow conversion between the different units where the conversions are fixed.

Enums

The current Java SE platform uses int constants for months, day-of-week, era and am-pm. ThreeTen uses the Java 5 Enum for these concepts to create a better API. The int values are retained internally, and may be used externally for months, where 1 is January and 12 is December.

 MonthOfYear month = date.getMonthOfYear();
 DayOfWeek dow = date.getDayOfWeek();
 if (month.isFebruary() and dow.isFriday()) ...

Invalid date strategy

What is the result when you add one month to the 31st of March? Is it the 30th of April? The 1st of May? An exception?

ThreeTen addresses this problem using the

DateResolver

strategy interface. Standard implementations are provided in

DateResolvers

.

 LocalDate date = LocalDate.of(2010, MonthOfYear.JANUARY, 31);
 LocalDate oneMonthLater = date.plusMonths(1, DateResolvers.previousValid());  // 28th Feb
 LocalDate oneMonthLater = date.plusMonths(1, DateResolvers.nextValid());      // 1st Mar

Adjustment strategy

How do you find the last day of the month? Or the next working day? Or a week on Tuesday?

ThreeTen addresses this problem using the

DateAdjuster

strategy interface. Standard implementations are provided in

DateAdjusters

.

 LocalDate date = LocalDate.of(2010, MonthOfYear.FEBRUARY, 26);
 LocalDate endOfMonth = date.with(DateAdjusters.lastDayOfMonth());
 LocalDate nextTue = date.with(DateAdjusters.next(DayOfWeek.TUESDAY));

Builder pattern

The builder pattern allows the object you want to be built up using individual parts. This is achieved using the methods prefixed by "at".

 // builder pattern
 OffsetDateTime dt = Year.of(2010).atMonth(MonthOfYear.FEBRUARY).atDay(26)
                        .atTime(12, 30).atOffset(ZoneOffset.of("+03:00"));
 // normal shorthand
 OffsetDateTime dt = OffsetDateTime.of(2010, 2, 26, 12, 30, ZoneOffset.of("+03:00"));

Current time

In ThreeTen, the current time is no longer obtained via

System.currentTimeMillis()

. Instead, the

TimeSource

class is used. This returns an instant based on the current time, or an altered instant suitable for testing. For the human-scale classes, the

Clock

class should used. This has methods to obtain all different kinds of date-time object, based on a time-source and a time-zone.

 @Inject
 private Clock clock

 public void process() {
   if (clock.today().getDayOfWeek().isMonday()) ...
 }

Time zones

In ThreeTen, time zones are represented by three co-operating classes.

The

ZoneOffset

class represents a fixed offset from UTC in seconds. This is normally represented as a string of the format "±hh:mm". Using a zone-offset is easier and safer than using a full time-zone as there are no gaps or overlaps in the local time-line when just using an offset. The

TimeZone

class represents the identifier for a region of the planet where time zone rules are defined and who has collated the data. The identifier consists of three parts:

  • the group that defines the rules - such as the TimeZone DB currently used by Java SE
  • the region - such as "Europe/London" (the region id is defined by the group)
  • the version - such as "2010b" (the version id is defined by the group)

The full identifier has the format {groupID}:{regionID}#{versionID} where the version id can be omitted (see below) and the group ID can be implied (as the standard TZDB used in java SE today).

The

ZoneRules

are the actual set of rules that define when the zone-offset changes. Each set of rules contains two parts - a list of historical transitions where the zone-offset has changed in the past, and a formula for calculating future changes. The rule information is fully accessible via the API. The

ZonedDateTime

class stores a

TimeZone

reference, rather than a

ZoneRules

. The time-zone must contain a group and a region, but the version may be blank, which indicates a "floating version". A "floating version" simply means that the

ZonedDateTime

class will use the latest available zone-rules. By comparison, if the date-time stores a time-zone with a specific version, then only that version of the rules can be used. This approach allows the time zone rules to be updated in a background thread while the application is running. The date-time object will pick up the changes on the next calculation is the version is floating or not at all if the version is specified.

The code to support background thread zone rules updates is not included in this JSR as it is more appropriate at the Java EE level.

Calendar systems

In ThreeTen, the standard civil calendar is considered to be the default and most classes are built around it. This calendar system is defined as the

ISOChronology

and models the time-line using the current rules for leap years over all time. It includes year 0 but omits leap seconds. To handle alternate calendar systems, a package of additional chronology and date classes is provided. Thus, to use the coptic date you should use the

CopticDate

class. Low level code can use the

Calendrical

interface to interoperate between different calendars. The ISO calendar system does not model historical dates accurately. The rules of the ISO calendar system were first introduced in 1582 and adopted by some European countries. However, some other countries did not adopt the system until into the 1900s. As such, it is always essential to check the software requirements when dealing with historical dates. ThreeTen provides the

HistoricDate

class to assist, which requires the cutover from the older Julian calendar system to the newer ISO/Gregorian system to be passed in.

Formatting

All standard ThreeTen have meaningful

toString

methods. The formatting package is there should more control be required. The formatting package supplies a set of standard formatters in

DateTimeFormatters

and a builder for complex formats in

DateTimeFormatterBuilder

. The end result is an instance of

DateTimeFormatter

which can be used to print to or parse from a string. Printing is based on an

Appendable

to allow direct output to a stream. The formatter is independent of the older Java SE Format class. However, a method

asFormat

allows a compatible formatter to be obtained.



Related

OldWiki: Early_Draft_Review
OldWiki: Main_Page
OldWiki: Old_home_page