Date and Time API - Platform - Java 8 Pocket Guide (2014)

Java 8 Pocket Guide (2014)

Part II. Platform

Chapter 18. Date and Time API

The Date and Time API (JSR 310) provides support for date, time, and calendar calculations. The reference implementation (RI) for this JSR is the ThreeTen Project and was provided for inclusion into JDK 1.8. The Date and Time API is relative to the java.time package andjava.time.chrono, java.time.format, java.time.temporal, and java.time.zone subpackages.

JSR 310 achieved several design goals:

§ Fluent API; easy-to-read (e.g., chained methods)

§ Thread-safe design; immutable value classes

§ Extensible API; calendar systems, adjusters, and queries

§ Expectable behavior

The Date and Time API uses the International Organization for Standardization date and time data exchange model (ISO 8601). The ISO 8601 standard is formally called “Data elements and interchange formats—Information interchange—Representation of dates and times.” The standard is based on the Gregorian calendar. Regional calendars are also supported.

See Appendix A for more information on fluent APIs.

Legacy Interoperability

JSR 310 supercedes but does not deprecate java.util.Date, java.util.Calendar, java.util.DateFormat, java.util.GregorianCalendar, java.util.TimeZone, and java.sql.Date. JDK 8 provides methods to these classes to convert to and from the JSR 310 types for legacy support.

// Legacy -> New -> Legacy

Calendar c = Calendar.getInstance();

Instant i = c.toInstant();

Date d = Date.from(i);

// New -> Legacy -> New

ZonedDateTime zdt

= ZonedDateTime.parse("2014-02-24T11:17:00+01:00"

+ "[Europe/Gibraltar]")

GregorianCalendar gc = GregorianCalendar.from(zdt);

LocalDateTime ldt

= gc.toZonedDateTime().toLocalDateTime();

Regional Calendars

JSR 310 is flexible enough to allow for the addition of new calendars. When creating a new calendar, classes will need to be implemented against the Era, Chronology, and ChronoLocalDate interfaces.

Four regional calendars are packaged with the API:

§ Hijrah

§ Japanese imperial

§ Minguo

§ Thai Buddhist

With regional calendars, you will not be using the main classes of the ISO calendar.

ISO Calendar

The primary java.time package of the API provides the ISO 8601 calendar system that is based on Gregorian rules. This and the related packages of the API provide an easy-to-use interface as you can see in the following example of determining age difference between presidents.

public final static String DISNEY_BIRTH_YEAR =

"1901";

public final static String TEMPLE_BIRTH_YEAR =

"1928";

...

Year birthYear1 = Year.parse(DISNEY_BIRTH_YEAR);

Year birthYear2 = Year.parse(TEMPLE_BIRTH_YEAR);

long diff

= ChronoUnit.YEARS.between(birthYear1,

birthYear2);

System.out.println("There is an age difference of "

+ Math.abs(diff) + " years." );

$ There is an age difference of 27 years.

The primary classes of the API are listed here with key text derived from the online API. The sections that follow highlight key attributes and usage of some of these classes.

Instant

Instantaneous point on the timeline; measured from the standard Java epoch of 1970-01-01T00:00:00Z.

LocalDate

Immutable date-time object;t represents a date, viewed as year-month-day.

LocalTime

Immutable date-time object that represents a time; viewed as hour-minute-second.

LocalDateTime

Immutable date-time object that represents a date-time; viewed as year-month-day-hour-minute-second.

OffsetTime

Immutable date-time object that represents a time; viewed as hour-minute-second-offset.

OffsetDateTime

Immutable representation of a date-time with an offset; stores all date and time fields to a precision of nanoseconds, as well as the offset from UTC/Greenwich.

ZonedDateTime

Immutable representation of a date-time with a time zone; stores all date and time fields to a precision of nanoseconds and a time zone, with a zone offset used to handle ambiguous local date-times.

ZoneOffset

Time-zone offset; amount of time that a time-zone differs from Greenwich/UTC.

ZonedId

Time-zone identification; used to identify the rules to convert between an Instant and a LocalDateTime.

Year

Immutable date-time object; represents a year.

YearMonth

Immutable date-time object; represents the combination of a year and month.

MonthDay

Immutable date-time object; represents the combination of a year and month.

DayOfWeek

Enumeration for the days of the week; Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, and Sunday.

Month

Enumeration for the months of the year; January, February, March, April, May, June, July, August, September, October, November, and December.

Duration

A time-based amount of time measured in seconds.

Period

A date-based amount of time.

Clock

A clock provides access to the current instant, date, and time using a time zone. It’s use is optional.

Machine Interface

JSR 310 uses the UNIX Epoch for its default ISO 8301 calendar with zero starting at 1970-01-01T00:00Z. Time is continuous since then, with negative values for instances before it.

To get an instance of the current time, simply call the Instant.now() method.

Instant i = Instant.now();

System.out.println("Machine: " + i.toEpochMilli());

$ Machine: 1392859358793

System.out.println("Human: " + i);

$ Human: 2014-02-20T01:20:41.402Z

The Clock class provides access to the current instant, date, and time while using a time zone.

Clock clock1 = Clock.systemUTC();

Instant i1 = Instant.now(clock1);

ZoneId zid = ZoneId.of("Europe/Vienna");

Clock clock2 = Clock.system(zid);

Instant i2 = Instant.now(clock2);

The Date-Time API uses the Time Zone Database (TZDB).

Durations and Periods

A Duration is a time-based amount consisting of days, hours, minutes, seconds, and nanoseconds. A duration is the time between two instances on a timeline.

The usage for a duration as a parsable string is PnDTnHnMnS where P stands for period and T stands for time. D, H, M, and S are days, hours, minutes, and seconds prefaced by their values (n):

Duration d1 = Duration.parse("P2DT3H4M1.1S");

Durations can also be created using the of[Type] method. Hours, minutes, seconds, and nanoseconds can be added to their associated status:

Duration d2 = Duration.of(41, ChronoUnit.YEARS);

Duration d3 = Duration.ofDays(8);

d3 = d3.plusHours(3);

d3 = d3.plusMinutes(30);

d3 = d3.plusSeconds(55).minusNanos(300);

The Duration.between() method can be used to create a Duration from a start and end time.

Instant birth = Instant.parse("1967-09-15T10:30:00Z");

Instant current = Instant.now();

Duration d4 = Duration.between(birth, current);

System.out.print("Days alive: " + d4.toDays());

A Period is a date-based amount consisting of years, months, and days.

The usage for a period as a parsable string is PnYnMnD where P stands for period; Y, M, and D are years, months, and days prefaced by their values (n):

Period p1 = Period.parse("P10Y5M2D");

Periods can also be created using the of[Type] method. Years, months, and days can be added or subtracted to/from their associated states.

Period p2 = Period.of(5, 10, 40);

p2 = p2.plusYears(100);

p2 = p2.plusMonths(5).minusDays(30);

JDBC and XSD Mapping

Interoperation between the java.time and java.sql types has been achieved. Table 18-1 provides a visual mapping of the JSR 310 types to the SQL as well as XML Schema (XSD) types.

Table 18-1. JDBC and XSD Mapping

JSR 310 Type

SQL Type

XSD Type

LocalDate

DATE

xs:time

LocalTime

TIME

xs:time

LocalDateTime

TIMESTAMP WITHOUT TIMEZONE

xs:dateTime

OffsetTime

TIME WITH TIMEZONE

xs:time

OffsetDateTime

TIMESTAMP WITH TIMEZONE

xs:dateTime

Period

INTERVAL

.

Formatting

The DateTimeFormatter class provides a formatting capability for printing and parsing date-time objects. The upcoming example demonstrates the use of pattern letters with the ofPattern() method of the class. Usable pattern letters are identified in the Javadoc for theDateTimeFormatter class:

LocalDateTime input = LocalDateTime.now();

DateTimeFormatter format

= DateTimeFormatter.ofPattern("yyyyMMddhhmmss");

String date = input.format(format);

String logFile = "simple-log-" + date + ".txt";

Table 18-2 contains examples of predefined formatters using the following structure:

System.out.print(LocalDateTime.now()

.format(DateTimeFormatter.BASIC_ISO_DATE));

Table 18-2. Predefined formatters

Class

Formatter

Example

LocalDateTime

BASIC_ISO_DATE

20140215

LocalDateTime

ISO_LOCAL_DATE

2014-02-15

OffsetDateTime

ISO_OFFSET_DATE

2014-02-15-05:00

LocalDateTime

ISO_DATE

2014-02-15

OffsetDateTime

ISO_DATE

2014-02-15-05:00

LocalDateTime

ISO_LOCAL_TIME

23:39:07.884

OffsetTime

ISO_OFFSET_TIME

23:39:07.888-05:00

LocalDateTime

ISO_TIME

23:39:07.888

OffsetDateTime

ISO_TIME

23:39:07.888-05:00

LocalDateTime

ISO_LOCAL_DATE_TIME

2014-02-15T23:39:07.888

OffsetDateTime

ISO_OFFSET_DATE_TIME

2014-02-15T23:39:07.888-05:00

ZonedDateTime

ISO_ZONED_DATE_TIME

2014-02-15T23:39:07.89-05:00 [America/New_York]

LocalDateTime

ISO_DATE_TIME

2014-02-15T23:39:07.891

ZonedDateTime

ISO_DATE_TIME

2014-02-15T23:39:07.891-05:00 [America/New_York]

LocalDateTime

ISO_ORDINAL_DATE

2014-046

LocalDate

ISO_WEEK_DATE

2014-W07-6

ZonedDateTime

RFC_1123_DATE_TIME

Sat, 15 Feb 2014 23:39:07 -0500