1. Overview

In this quick tutorial, we’re going to take a look at two new classes for working with dates introduced in Java 8: Period and Duration.

Both classes can be used to represent an amount of time or determine the difference between two dates. The main distinction between the two classes is that Period uses date-based values, while Duration uses time-based values.

2. Period Class

The Period class uses the units year, month and day to represent a period of time.

We can obtain a Period object as the difference between two dates by using the between() method:

LocalDate startDate = LocalDate.of(2015, 2, 20);
LocalDate endDate = LocalDate.of(2017, 1, 15);

Period period = Period.between(startDate, endDate);

Then, we can determine the date units of the period using the methods getYears(), getMonths(), getDays():

LOG.info("Years:" + period.getYears() + 
  " months:" + period.getMonths() + 
  " days:"+period.getDays());

In this case, the isNegative() method, which returns true if any of the units are negative, can be used to determine if the endDate is higher than the startDate:

assertFalse(period.isNegative());

If isNegative() returns false, then the startDate is earlier than the endDate value.

Another way to create a Period object is based on the number of days, months, weeks or years using dedicated methods:

Period fromUnits = Period.of(3, 10, 10);
Period fromDays = Period.ofDays(50);
Period fromMonths = Period.ofMonths(5);
Period fromYears = Period.ofYears(10);
Period fromWeeks = Period.ofWeeks(40);

assertEquals(280, fromWeeks.getDays());

If only one of the values is present, for example by using the ofDays() method, then the value of the other units is 0.

In the case of the ofWeeks() method, the parameter value is used to set the number of days by multiplying it by 7.

We can also create a Period object by parsing a text sequence, which has to have the format “PnYnMnD”:

Period fromCharYears = Period.parse("P2Y");
assertEquals(2, fromCharYears.getYears());

Period fromCharUnits = Period.parse("P2Y3M5D");
assertEquals(5, fromCharUnits.getDays());

The value of the period can be increased or decreased by using methods of the form plusX() and minusX(), where X represents the date unit:

assertEquals(56, period.plusDays(50).getDays());
assertEquals(9, period.minusMonths(2).getMonths());

3. Duration Class

The Duration class represents an interval of time in seconds or nanoseconds and is most suited for handling shorter amounts of time, in cases that require more precision.

We can determine the difference between two instants as a Duration object using the between() method:

Instant start = Instant.parse("2017-10-03T10:15:30.00Z");
Instant end = Instant.parse("2017-10-03T10:16:30.00Z");
        
Duration duration = Duration.between(start, end);

Then we can use the getSeconds() or getNanoseconds() methods to determine the value of the time units:

assertEquals(60, duration.getSeconds());

Alternatively, we can obtain a Duration instance from two LocalDateTime instances:

LocalDateTime start = LocalDateTime.parse("2020-01-01T08:00:00");
LocalDateTime end = LocalDateTime.parse("2023-01-01T12:00:00");

Duration.between(start, end).getSeconds();

Depending on the start and end time points, a Duration can be:

  • Negative: start < end
  • Zero: start = end
  • Positive: start > end

Also, the standard Time API offers convenient methods to check if a Duration is Zero or Negative:

LocalDateTime start = LocalDateTime.parse("2020-01-01T08:00:00");
LocalDateTime end = LocalDateTime.parse("2020-01-01T12:00:00");
assertFalse(Duration.between(start, end).isNegative());
assertTrue(Duration.between(end, start).isNegative());

LocalDateTime theTime = LocalDateTime.parse("2023-09-09T08:00:00");
assertTrue(Duration.between(theTime,theTime).isZero());
assertFalse(Duration.between(theTime,theTime).isNegative());

It’s worth noting that before Java 18, the Duration class only provided isZero() and isNegative(). The Duration.isPositive() method has been introduced since Java version 18:

// Java version 18+ required
LocalDateTime start = LocalDateTime.parse("2020-01-01T08:00:00");
LocalDateTime end = LocalDateTime.parse("2020-01-01T12:00:00");
assertTrue(Duration.between(start, end).isPositive());
assertFalse(Duration.between(end, start).isPositive());

We can also obtain a Duration object based on several time units, using the methods ofDays(), ofHours(), ofMillis(), ofMinutes(), ofNanos(), ofSeconds():

Duration fromDays = Duration.ofDays(1);
assertEquals(86400, fromDays.getSeconds());
       
Duration fromMinutes = Duration.ofMinutes(60);

To create a Duration object based on a text sequence, this has to be of the form “PnDTnHnMn.nS“:

Duration fromChar1 = Duration.parse("P1DT1H10M10.5S");
Duration fromChar2 = Duration.parse("PT10M");

A duration can be converted to other time units using toDays(), toHours(), toMillis(), toMinutes():

assertEquals(1, fromMinutes.toHours());

A duration value can be increased or decreased by using methods of the form plusX() or minusX(), where X can stand for days, hours, millis, minutes, nanos or seconds:

assertEquals(120, duration.plusSeconds(60).getSeconds());     
assertEquals(30, duration.minusSeconds(30).getSeconds());

We can also use the plus() and minus() methods with a parameter that specifies the TemporalUnit to add or subtract:

assertEquals(120, duration.plus(60, ChronoUnit.SECONDS).getSeconds());     
assertEquals(30, duration.minus(30, ChronoUnit.SECONDS).getSeconds());

4. Conclusion

In this article, we’ve seen how we can use the Period and Duration classes.

As always, the full source code of the examples can be found over on GitHub.