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 |