Java 8 Date and time API: the LocalDate class
September 24, 2016 Leave a comment
The Date and time API in Java 8 has been completely revamped. Handling dates, time zones, calendars etc. had been cumbersome and fragmented in Java 7 with a lot of deprecated methods. Developers often had to turn to 3rd party date handlers for Java such as Joda time.
One of many new key concepts in the java.time package of Java 8 is the immutable LocalDate class. A LocalDate represents a date at the level of days such as April 04 1988.
You can easily get hold of the current date of the default time zone of the local computer – in my case it’s CET:
LocalDate localDate = LocalDate.now();
…or you can construct a date using the static “of” method:
LocalDate someDayInApril = LocalDate.of(1988, Month.APRIL, 4);
LocalDate comes with the following constants:
- LocalDate.MAX: ranges until year-month-day of ‘+999999999-12-31’
- LocalDate.MIN: reaches as far back as years-months-days ‘-999999999-01-01’
The Period class is strongly related to LocalDate. You can find the time span between two LocalDate instances using the “until” method which returns a Period object:
Period timeSpan = someDayInApril.until(localDate); int years = timeSpan.getYears(); int months = timeSpan.getMonths(); int days = timeSpan.getDays();
At the time of writing this post there were 26 years, 6 months and 27 days between the two dates.
The Period class has a static “between” method to achieve the same:
Period between = Period.between(someDayInApril, localDate);
…which yields the same time difference as the “until” method above.
A period can be normalised so that values like 13 months can be changed to 1 year and 1 month instead. Let’s create a 23-month period and normalise it:
Period ofMonths = Period.ofMonths(23); Period normalized = ofMonths.normalized();
“normalized” will have 1 year and 11 months for the getYears and getMonths values respectively. “ofMonth” would have 0 years and 23 months instead.
Let’s test this with days:
Period ofDays = Period.ofDays(4322); Period daysNormalised = ofDays.normalized();
In this case, however, both will yield getDays = 4322, years and months will be 0. This is expected as the number of days in a month can vary so the calculation would be based on some average, like 30 days at best but that result would almost certainly be incorrect. The previous example succeeded as the number of months in a year is set.
The isZero() method of Period returns true if we compare two periods and they refer to the same date:
Period zeroPeriod = someDayInApril.until(someDayInApril); boolean zero = zeroPeriod.isZero();
…zero will be “true”.
Negative periods occur if we compare two LocalDate instances and take the later date as point of reference in the comparison:
Period negativePeriod = localDate.until(someDayInApril); boolean negative = negativePeriod.isNegative();
“negative” will be true. The year, month and day values will be -26, -6 and -27.
You can easily transform that into a positive period though:
Period negated = negativePeriod.negated();
The year, month and day values of “negated” will be 26, 6 and 27.
You can multiply a Period with an integer which will multiply the year, month and day values with that integer without normalising the date. So in case you need to get a twice as long period you can do as follows:
Period twiceAsLong = ofDays.multipliedBy(2);
Plus and minus methods
Both the LocalDate and the Period classes have methods whose names start with “plus” or “minus” which serve to add or subtract a certain amount of time to and from a date/period. Examples:
LocalDate plusDays = localDate.plusDays(20); LocalDate minusYears = localDate.minusYears(15); Period minusMonths = between.minusMonths(11);
You can probably guess what these operations do.
Total number of time units
What if you’d like to know the total number of days between two LocalDate instances? The “until” method has an overload that you can use. E.g. here’s how you find the total number of days between “localDate” and “someDayInApril”:
long until = someDayInApril.until(localDate, ChronoUnit.DAYS);
…which at this time gives 9706 days. The ChronoUnit enumeration in the java.time.temporal package has other values to find the total number of “x” between two local dates but not all of them are supported in the “until” operation. E.g. you cannot calculate the number of hours or nanoseconds between two LocalDate instances. Any level of detail more fine grained than DAYS will throw an exception of type java.time.temporal.UnsupportedTemporalTypeException as LocalDate is only available at the day level: there’s no concept of hours, minutes etc. in the case of LocalDate.
In the next post we’ll look at the LocalTime class.
View all posts related to Java here.