Font Awesome Free 5.13.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
Skip to main content

Date and Time API (Java)

An overview of the Java Date and Time API

Date and Time API basics​

Java 1.0 had Date, most methods deprecated with introduction of Calendar in Java 1.1. Still not perfect (sometimes awkward API, didn't deal with leap seconds, ...) -> the recommendation used to be to use a library like Joda Time instead.

Java 8 introduced a new Data and Time API under java.time, which solves a lot of the issues with the older solutions.

Some key points:

  • All instances of java.time objects are immutable (operations that change dates or times return new objects)
  • A day has exactly 86400 seconds (leap seconds are dealt with by making seconds last a little bit longer)

Instants and Durations​

Instant: represents a point on the time line

Duration: represents the amount of time between two instants

Instant start = Instant.now();
// perform some computations
Instant end = Instant.now();
Duration timeElapsed = Duration.between(start, end);
long millis = timeElapsed.toMillis();
Duration oneWeek = Duration.ofDays(7);
long secondsInWeek = oneWeek.toSeconds();

Computations with durations:

  • Option 1: use methods directly on durations
  • Option 2: convert to nanoseconds
    • Note that a long of nanoseconds doesn't allow you to use the entire range of a Duration, but it a long can hold almost 300 years worth of nanoseconds
// Option 1
if (duration1.multipliedBy(10).minus(duration2).isNegative()) {
// ...
}

// Option 2
if (duration1.toNanos() * 10 < duration2.toNanos()) {
// ...
}

Local dates and time​

Local date/time: has a date and/or time of day, but no time zone information

Example use cases:

  • Someone's birthday (this refers to a certain calendar date, but not to a precise instant on the time line)
  • Calculations with date and time when you want to ignore time zones and don't want daylight savings time to be taken into account
    • Example: a meeting that is at 10:00 every 7 days (regardless of daylight savings time)
    • Note: you can also ignore daylight savings time when working with zoned times, see below

Local dates​

LocalDate today = LocalDate.now();
LocalDate test1 = LocalDate.of(2019, 8, 28);
LocalDate test2 = LocalDate.of(2019, Month.AUGUST, 28);
System.out.println(test1.equals(test2)); // true
LocalDate programmersDay = LocalDate.of(2019, 1, 1).plusDays(255);
// Duration.ofYears(1) wouldn't produce the correct result in a leap year
LocalDate birthdayNextYear = birthday.plus(Period.ofYears(1));
today.until(christmas, ChronoUnit.DAYS) // get # days until Christmas

Note: methods adjusting dates don't throw exceptions if the result would be invalid but adjust it to a valid date instead!

LocalDate test = LocalDate.of(2016, 1, 31).plusMonths(1);
System.out.println(test); // 2016-02-29

Temporal adjusters​

Example: compute first Tuesday of a month

LocalDate firstTuesday = LocalDate.of(year, month, 1).with(
TemporalAdjusters.nextOrSame(DayOfWeek.TUESDAY))

Local time​

LocalTime currentTime = LocalTime.now();
LocalTime bedTime = LocalTime.of(00, 30);
LocalTime alarmTime = bedTime.plusHours(8);

Zoned time​

Zoned time: date and time plus time zone information

  • Represents particular instant in time
  • When performing calculations or transforming between time zones, daylight savings time and time zone rules are taken into account
ZonedDateTime apolloLaunch = ZonedDateTime.of(1969, 7, 16, 9, 32, 0, 0,   
ZoneId.of("America/New_York"));

System.out.println(apolloLaunch); // 1969-07-16T09:32-04:00[America/New_York]
Instant now = Instant.now();
ZonedDateTime nowInUtc = now.atZone(ZoneId.of("UTC"));
// Duration.ofDays(7) wouldn't work with daylight savings time
ZonedDateTime nextMeeting = currentMeeting.plus(Period.ofDays(7))

Note: there is also OffsetDateTime, which uses a fixed offset from UTC. This is useful for some technical applications like network protocols. For dealing with human time, ZonedDateTime is typically the best option.

Formatting and parsing dates​

The DateTimeFormatter class now replaces the old DateTimeFormat (you can still call toFormat() on a DateTimeFormatter to get a legacy DateTimeFormat)

// predefined ISO_OFFSET_DATE_TIME format (ISO-8601-compliant)
String formatted = DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(ZonedDateTime.now());
System.out.println(formatted); // 2019-08-28T16:02:07.5384469+02:00
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);
String formatted = formatter.format(ZonedDateTime.now());
System.out.println(formatted); // August 28, 2019 at 4:05:04 PM CEST
LocalDate parsed1 = LocalDate.parse("2019-08-28");
DateTimeFormatter patternFormatter = DateTimeFormatter.ofPattern("yyyy/dd/MM");
LocalDate parsed2 = LocalDate.parse("2019/28/08", patternFormatter);
System.out.println(parsed1.equals(parsed2)); // true

// throws DateTimeParseException
LocalDate parsed3 = LocalDate.parse("2019/08/28", patternFormatter);

Resources​

  • Core Java SE 9 for the Impatient (book by Cay S. Horstmann)