A look into Java 8 Date-Time API

Did you just set up your environment to start working with java 8? Jump right to the chapter of lambda or ran across just about every blog that gives you examples? There is more to java 8 than just lambdas!

If you have worked with java dates you have pulled your hair while using java.util.Date, java.util.Calendar, java.util.GregorianCalendar. If you ran across joda time library most likely you are using it. If not, luckily with java 8 and the development of JSR 310: Date and Time API it will easier to use date time methods. The goal was Date-Time API clarity in method constructs, cleaner readable code, immutable and extensibility. Oh yea, we even got Day of the week and month enums!

High level classes in API

For the most part the date time trail does a good job describing the new classes, below are a few to focus on first:

ClassDescription
LocalDateRepresenting a date without a time
LocalDateTimeHandles both date and time
PeriodIs a date based amount of time in terms of years
DurationMeasures time in seconds or nano seconds
ChronoUnitDefines units used to measure time. For example, if you need to find the number of days between two dates, ChronoUnit.DAYS.between(localdate1, localdate2)
DateTimeFormatterFormatter for printing and parsing date-time objects

Moving from JODA to Java 8 date-time API

While working on updating java date examples the API is clean. Converting from JODA to java 8 date time API should natural switch while converting from legacy java date-time will be a slight learning curve. Here is a high level comparison between joda and the new java 8 date time api:

Joda timeJava 8 date-time APIDescription
DateTime.isAfterLocalDate.isAfter, LocalDateTime.isAfterChecks if a date is after the specified date
DateTime.isBeforeLocalDate.isBefore, LocalDate.isBeforehecks if a date is before the specified date
Years.between, Weeks.weeksBetween, Seconds.secondsBetween, etc...ChronoUnit.DAYS.between, Period.between, Duration.betweenCalculates the amount of time between two date objects. For ChronoUnit subsitute DAYS, YEARS, etc
DateTime.withYear(2007).year().isLeap()Year.of(2007).isLeap(), LocalDate.ofYearDay(2007, 1).isLeapYear()Checks if the year is a leap year
DateTimeFormatter.parseDateTimeLocalDate.parse, LocalDateTime.parseConvert text string to a date
org.joda.time.format.DateTimeFormatter DateTime.toString(format)java.time.format.DateTimeFormatter LocalDate.format, LocalDateTime.formatFormats date to a specified string format.
DateTime.minusDays, DateTime.minusWeeksLocalDate.minusDays, LocalDate.minusMonthsSubtract specified number of months, days, year
DateTime.plusDays, DateTime.plusWeeks, etcLocalDateTime.plusDays, LocalDateTime.plusHours, etcAdd specified number of months, days, year
DateTime.nowLocalDate.now(), LocalDateTime.nowGet current date time

At first misunderstood

UnsupportedTemporalTypeException explained

UnsupportedTemporalTypeException indicates that a ChronoField or ChronoUnit is not supported for a Temporal class. I ran across this error while updating the number of hours between two dates. Thinking through the example below, I wanted to get today, subtract 1 day and then find the number hours between the dates. This resulted in UnsupportedTemporalTypeException because LocalDate only contains year, month and day fields not hours. It makes sense now but be aware when trying to access fields on temporal objects.

@Test
public void hours_between_two_dates_in_java_with_java8 () {

    LocalDate startDate = LocalDate.now().minusDays(1);
    LocalDate endDate = LocalDate.now();

    long days = ChronoUnit.HOURS.between(startDate, endDate);

    assertEquals(24, days);
}
java.time.temporal.UnsupportedTemporalTypeException: Unsupported unit: Hours
    at java.time.LocalDate.until(LocalDate.java:1608)
    at java.time.temporal.ChronoUnit.between(ChronoUnit.java:272)
    at com.levelup.java.date.between.HoursBetweenDates.hours_between_two_dates_in_java_with_java8(HoursBetweenDates.java:31)

Using Period to find hours

While working through hours between dates example. I started by using Period but period is represented by all three units together: months, days, and years. So lets say I wanted to find the difference between my birthday and today. Using period would result in output that could look like 53 years, 4 months, and 29. When you want to find a single unit of time use ChronoUnit.between

The hour example using ChronoUnit.between:

@Test
public void hours_between_two_dates_in_java_with_java8 () {

    LocalDateTime startDate = LocalDateTime.now().minusDays(1);
    LocalDateTime endDate = LocalDateTime.now();

    long numberOfHours2 = ChronoUnit.HOURS.between(startDate, endDate);
    assertEquals(24, numberOfHours2);
}

Updated examples

I updated all the date time examples to use Java 8 date time api. Below are just a few: