home

Date & Time

Overview

Cheat Sheet

Following table taken from this page.

Class or Enum Year Month Day Hours Minutes Seconds* Zone Offset Zone ID toString Output
Instant          
    2013-08-20T15:16:26.355Z
LocalDate
          2013-08-20
LocalDateTime
    2013-08-20T08:16:26.937
ZonedDateTime
2013-08-21T00:16:26.941+09:00[Asia/Tokyo]
LocalTime      
    08:16:26.943
MonthDay  
          --08-20
Year
              2013
YearMonth
            2013-08
Month  
            AUGUST
OffsetDateTime
  2013-08-20T08:16:26.954-07:00
OffsetTime      
  08:16:26.957-07:00
Duration     ** ** **
    PT20H (20 hours)
Period
      *** *** P10D (10 days)
*   Seconds are captured to nanosecond precision.
**  This class does not store this information, but has methods to provide time in these units.
*** When a Period is added to a ZonedDateTime, daylight saving time or other local time differences are observed.

Date & Time Constants

ChronoUnit

enum ChronoUnit implements TemporalUnit {
    NANOS, MICROS, MILLIS, SECONDS, MINUTES, HOURS, HALF_DAYS, DAYS, WEEKS, MONTHS, YEARS, DECADES, CENTURIES, 
    MILLENNIA, ERAS, FOREVER
}

ChronoField

enum ChronoField implements TemporalField {
    NANO_OF_SECOND, NANO_OF_DAY, MICRO_OF_SECOND, MICRO_OF_DAY, MILLI_OF_SECOND, MILLI_OF_DAY, SECOND_OF_MINUTE, 
    SECOND_OF_DAY, MINUTE_OF_HOUR, MINUTE_OF_DAY, HOUR_OF_AMPM, CLOCK_HOUR_OF_AMPM, HOUR_OF_DAY, 
    CLOCK_HOUR_OF_DAY, AMPM_OF_DAY, DAY_OF_WEEK, ALIGNED_DAY_OF_WEEK_IN_MONTH, ALIGNED_DAY_OF_WEEK_IN_YEAR, 
    DAY_OF_MONTH, DAY_OF_YEAR, EPOCH_DAY, ALIGNED_WEEK_OF_MONTH, ALIGNED_WEEK_OF_YEAR, MONTH_OF_YEAR, 
    PROLEPTIC_MONTH, YEAR_OF_ERA, YEAR, ERA, INSTANT_SECONDS, OFFSET_SECONDS    
}

See also: Difference between ChronoUnit and ChronoField

Instant

Creating an Instant

// Capture the current moment in UTC
Instant.now();              // 2018-11-28T01:51:48.847Z

// Get the epoch
Instant.EPOCH;              // 1970-01-01T00:00:00Z

// Reminder: 1000 milliseconds = 1 second
Instant.ofEpochMilli(1000); // 1970-01-01T00:00:01Z

Further Reading

Creating an Instant from a Temporal Object

// ZonedDateTime is supported
Instant.from(ZonedDateTime.now()); // 2018-11-29T03:38:33.905Z

// LocalDateTime is not supported
Instant.from(LocalDateTime.now()); // UnsupportedTemporalTypeException: Unsupported field: InstantSeconds

Updating an Instant

Heads Up! java.time.Instant is an immutable class an update methods return new instances instead of updating the instance itself.

// I find it interesting that this compiles and runs fine
Instant now = Instant.now();
now = now.plus(1, ChronoUnit.DAYS); // 2019-01-14T16:19:07.939Z

Duration

A Duration measures an amount of time using time-based values, i.e. hours, minutes, seconds..

The Java™ Tutorials

Creating a Duration

Creating a Duration with Constants

// Creating a Duration with ofNanos, ofSeconds, ofMillis, ofMinutes, ofHours, ofDays
Duration.ofNanos(1); // PT0.000000001S
Duration.ofDays(1);  // PT24H

Creating a Duration from Duration Between Temporals

// Using Instant
Duration.between(Instant.EPOCH, Instant.now()); // PT428714H19M29.54S

// Using LocalTime
LocalTime now = LocalTime.now();
Duration.between(now.minusHours(1).minusMinutes(30).minusSeconds(15), now); // PT1H30M15S

// LocalDate is NOT supported
// Duration.between(LocalDate.now(), LocalDate.now())
// java.time.temporal.UnsupportedTemporalTypeException: Unsupported unit: Seconds

Reading a Duration

Duration d = Duration.between(Instant.EPOCH, Instant.now());
d.toDays()  // 17864
d.toHours() // 428738
// Also available: toNanos(), toMillis(), getSeconds(), toMinutes()

Why can't I get a duration in minutes or hours in java.time?

.. that get(TemporalUnit) is essentially a framework-level method - it is not designed for day-today use. Unfortunately the method name get does not imply this, resulting in bugs like calling get(ChronoUnit.MINUTES) on Duration

Updating a Duration

// Reminder: a new instance is returned
Duration d = Duration.ofHours(1);
d = d.plusMinutes(30); // PT1H30M

Using Duration as TemporalAmount

Duration extends TemporalAmount which is used in various places in the API.

// Example with Instant.plus(TemporalAmount)
Duration dayz = Duration.ofDays(20000); // 20000 days
Instant.EPOCH.plus(dayz);               // 2024-10-04T00:00:00Z

// Example with LocalTime.plus(TemporalAmount)
LocalTime localTime = LocalTime.of(12, 0);
Duration halfAnHour = Duration.ofMinutes(30);
localTime.plus(halfAnHour)  // 12:30

Period

A Period measures an amount of time using date-based values, i.e. years, months, days..

The Java™ Tutorials

Why can I not get number of calendar days from a Period?

.. it is not possible from a Period to deduce the actual number of calendar days in the period. A Period is not tied to specific dates, once constructed in the way you show, it loses track of the actual calendar dates.

For example your first period represents a period of 1 month and 1 day. But the period does not care which month. It is simply a concept of "a month and a day".

To get number of days between two dates, use ChronoUnit.DAYS.between(Temporal, Temporal) ..

How to calculate the number of days in a period? - StackOverflow

Creating a Period

// Period of years, months, days
Period.of(1, 1, 1); // P1Y1M1D
Period.ofDays(45);  // P45D
// also available: ofMonths, ofYears

A Small Brain Teaser

Does the following code compile? Run without any exceptions? What is the returned instance? (A period of .. ..?)

Period.ofYears(1).ofMonths(1).ofDays(1);

LocalDate

Creating a LocalDate

LocalDate.now();                // 2018-11-25
LocalDate.of(1984, 9, 3);       // 1984-09-03
LocalDate.parse("1984-09-03");  // 1984-09-03
// There is no direct link between an Instant and a LocalDate

Reading a LocalDate

LocalDate ld = LocalDate.of(1984, 9, 3);
ld.getDayOfWeek();  // DayOfWeek.MONDAY
ld.getDayOfMonth(); // 3
ld.getDayOfYear();  // 247
LocalDate ld = LocalDate.of(1984, 9, 3);
ld.getMonth();      // Month.SEPTEMBER
ld.getMonthValue(); // 9

Reading Various Properties from a LocalDate

LocalDate ld = LocalDate.of(1984, 9, 3);
ld.lengthOfMonth(); // 30
ld.isLeapYear();    // true
ld.lengthOfYear();  // 366 

Finding Duration Between LocalDates using ChronoUnit

ChronoUnit.DAYS.between(LocalDate.now(), LocalDate.now().minusDays(1)); // 1L

Updating a LocalDate

Heads Up! java.time.LocalDate is an immutable class an update methods return new instances instead of updating the instance itself.

LocalDate ld = LocalDate.of(1983, 9, 3);
ld.plusYears(1);    // 1984-09-03 ➤ This is most likely what you want
ld.plusDays(365);   // 1984-09-02 ➤ It is not the 3rd of 84 due to leap year

// Using Period
ld.plus(Period.ofYears(1));  // 1984-09-03 ➤ This is most likely what you want
ld.plus(Period.ofDays(365)); // 1984-09-02 ➤ It is not the 3rd of 84 due to leap year

// Trying to update a LocalDate with a Duration will throw a Runtime Exception
LocalDate.now().plus(Duration.ofDays(1));
// java.time.temporal.UnsupportedTemporalTypeException: Unsupported unit: Seconds

Comparing LocalDates

LocalDate.now().equals(LocalDate.now());  // true
LocalDate.now().isEqual(LocalDate.now()); // true

LocalTime

Creating a LocalTime

Creating a new LocalTime

LocalTime.of(22, 30);     // 22:30
LocalTime.of(22, 30, 45); // 22:30:45
LocalTime.parse("22:30"); // 22:30
LocalTime.now();          // 22:57:36.162

LocalDateTime

Creating a LocalDateTime

Creating a LocalDateTime using an Instant

Instant now = Instant.now();
LocalDateTime.ofInstant(now, ZoneOffset.UTC);               // 2018-12-23T15:22:27.016
LocalDateTime.ofInstant(now, ZoneId.of("America/Toronto")); // 2018-12-23T10:22:27.016

ZonedDateTime

Creating a ZonedDateTime

ZonedDateTime.now();                            // 2018-11-28T23:30:08.454-05:00[America/Toronto]
ZonedDateTime.now(Clock.systemDefaultZone());   // 2018-11-28T23:30:08.456-05:00[America/Toronto]
ZonedDateTime.now(Clock.systemUTC());           // 2018-11-29T04:30:08.456Z

ZonedDateTime from LocalDate

LocalDate ld = LocalDate.of(1984, 9, 3);
// Basically attaching time zone information to a particular date
ld.atStartOfDay(ZoneId.of("America/Toronto")); // 1984-09-03T00:00-04:00[America/Toronto]
ld.atStartOfDay(ZoneId.of("Europe/Istanbul")); // 1984-09-03T00:00+03:00[Europe/Istanbul]

Finding Time in a Different Zone

Instant now = Instant.now();
ZonedDateTime.ofInstant(now, ZoneId.of("America/Toronto")); // 2018-12-23T10:41:45.322-05:00[America/Toronto]
zdt.withZoneSameInstant(ZoneId.of("Europe/Istanbul"));      // 2018-12-23T18:41:45.322+03:00[Europe/Istanbul]

Updating a ZonedDateTime

// DayLightSavings time for Toronto in 2019: Sunday, March 10, 2:00 am
ZonedDateTime zdt = 
ZonedDateTime.of(
    LocalDate.of(2019, 3, 10),
    LocalTime.of(1, 0),
    ZoneId.of("America/Toronto"));    // 2019-03-10T01:00-05:00[America/Toronto]
zdt = zdt.plus(Duration.ofHours(1));  // 2019-03-10T03:00-04:00[America/Toronto]

TemporalAdjuster

class NextWorkingDay implements TemporalAdjuster {
    @Override
    public Temporal adjustInto(Temporal temporal) {
        LocalDate nw = ((LocalDate) temporal).plusDays(1);
        while (nw.getDayOfWeek() == DayOfWeek.SATURDAY || nw.getDayOfWeek() == DayOfWeek.SUNDAY) {
            nw = nw.plusDays(1);
        }
        return nw;
    }
}

class FirstTuesdayOfAMonth implements TemporalAdjuster {
    @Override
    public Temporal adjustInto(Temporal temporal) {
        LocalDate ld = ((LocalDate) temporal).with(TemporalAdjusters.firstDayOfMonth());
        while (ld.getDayOfWeek() != DayOfWeek.TUESDAY) {
            ld = ld.plusDays(1);
        }
        return ld;
    }    
}

LocalDate.now().with(new NextWorkingDay());
LocalDate.now().with(new FirstTuesdayOfAMonth());

Examples

Daylight Saving Times

final Set<ZonedDateTime> dayLightSavingZonedDateTimes = new HashSet<>();

ZoneId.getAvailableZoneIds().forEach(zoneId -> {
    LocalDateTime dateTime = LocalDateTime.of(LocalDate.of(2018, 1, 1), LocalTime.of(0, 0, 0));
    ZonedDateTime now = ZonedDateTime.of(dateTime, ZoneId.of(zoneId));
    while (2018 == now.getYear()) {
        int hour = now.getHour();
        now = now.plusHours(1);
        if (now.getHour() == hour) {
            dayLightSavingZonedDateTimes.add(now);
        }
    }
});

dayLightSavingZonedDateTimes.stream().limit(5).forEach(time -> System.out.println(time));

// 2018-11-04T01:00-05:00[America/Indiana/Petersburg]
// 2018-11-04T01:00-10:00[US/Aleutian]
// 2018-10-28T02:00+01:00[Europe/Brussels]
// 2018-10-28T03:00+02:00[Europe/Sofia]
// 2018-10-28T02:00+01:00[Europe/Vienna]

Day of the Programmer

// Print the Day of the Programmer (the 256th day of the year) for 2011 and 2012
IntStream.rangeClosed(2011, 2012).forEach(year -> {
    LocalDate programmersDay = LocalDate.of(year, 1, 1).plusDays(255);
    System.out.println(programmersDay);
});

// 2011-09-13
// 2012-09-12

Number of Days until Next Birthday

LocalDate today = LocalDate.now();
LocalDate nextBirthday = LocalDate.of(1984, 9, 3).withYear(today.getYear());

if (ChronoUnit.DAYS.between(today, nextBirthday) <= 0) // If birthday this year passed already
    nextBirthday = nextBirthday.plusYears(1);

ChronoUnit.DAYS.between(today, nextBirthday); // long

References

TODO

It's not possible to do that directly, since the LocalDateTime family of objects has no notion of what time zone they're in. Thus time zone information needs to be supplied to find the time relative to the epoch, which is in UTC.

How to get milliseconds from LocalDateTime in Java 8 - StackOverflow