Java Time Package


Reading time: 35 minutes | Coding time: 10 minutes

At Java Standard Edition 8 was included a new API package to handle with date-time concepts. When imported, the "java time" gives access to classes like Instant, LocalTime, LocalDate, OffsetTime, and others. All of them follow the ISO calendar system defined by the proleptic Gregorian rules.

Before that, Java has two separate packages to handle this type of information, java.util.Calendar and java.util.Date. Both have two main issues: they are no thread safe and don't support time zone information. It's up to the developer to get around the possible troubles using these classes in a multi-thread scenario and add additional logic to deal with different time zones.

The new API introduced in SE 8 solves these problems, also bringing more friendly methods and documentation, helping programmers to use its features without creating headaches with new obstacles appearing.

This article brings a brief introduction to some classes available by the Date/Time Java API, with samples to the main characteristics of each one of them.

import java.time.*;

Date and Time

First of all, let's introduce the two main classes from the package and some of the numerous ways to handle its information: LocalDate and LocalTime.

When developing a system, many times it will be needed to have access to the current date, be to keep your logs in a chronology order, to save the day of the database insertion, or verify if a reminder wasn't set up for the past year, in all these cases the developer can make a class with just a few variables like day, month and year. However, the amount of additional logic needed to implements date operations it's immense and unnecessary.

The LocalDate class delivers an API to obtain and manipulate the current operating system date information, caring all the logic to add days, weeks, and other operations without losing data consistency.

// Return current system date
LocalDate date = LocalDate.now();

To get a specific date and save in a variable it can be used the of() method with the literal values to year, month, and day of the month has parameters, or even sending a string to the parse() method, some combinations of both are in the code below.

// Return a Local Date object in 07-21-1995
LocalDate date = LocalDate.of(1995, 07, 21);
// Return a Local Date object in 04-05-2019
date = LocalDate.parse("2019-04-05");
// Return a Local Date object in 12-25-1995
date = LocalDate.parse("25/12/1995", DateTimeFormatter.ofPattern("d/M/y"));

The LocalTime class works similarly to LocalDate. With the only distinction of dealing with hours, minutes, seconds, and nanoseconds. Apart from that, both have very similar behavior. An example of this is that the methods showed before will return a resembling result.

// System current time
LocalTime localTime = LocalTime.now();
// LocalTime object with specific hour and minute 23:45
LocalTime localTime = LocalTime.of(23, 45);
// LocalTime object with specific hour, minute and seconds 23:45:12
LocalTime localTime = LocalTime.of(23, 45, 12);
// LocalTime object with specific hour, minute, seconds and nanoseconds 23:45:12:500000000
LocalTime localTime = LocalTime.of(23, 45, 12, 500000000);

Some useful operations available in this Java package are related to add and subtract some amounts from our date/time objects and compare to distinct dates to which one comes first in chronological order. Adding days to a LocalDate can be done with the plusDays() method while subtracting hours to a LocalTime perform with the minusHours() one. Compare date/time objects it's possible in two ways, by using the isBefore(), isAfter(), and isEqual() methods which return a boolean value, or using the int returned by the compareTo() method, fitting for the three situations. It's also possible to get the interval between two dates or two times through until().
The following code has some examples of the topics discussed just now.

// LocalDate of seven days from now
LocalDate date = LocalDate.now().plusDays(7);
// LocalTime of 12 hours before now
LocalTime localTime = LocalTime.now().minusHours(12);

boolean isbeforeDate = date.isBefore(LocalDate.now()); // false
boolean isafterTime = localTime.isAfter(LocalTime.now().minusHours(30)); //true

// Comparing two dates, returns negative if the comparator is less, positive if is more and zero if equals
int compareDates = date.compareTo(LocalDate.now().plusMonths(3)); // returns -1 

LocalDate yesterday = LocalDate.now().minusDays(1);
// Period object from yesterday until a specificdate
Period period = yesterday.until(date);
// Months until specific date
long untilMonths = yesterday.until(date, ChronoUnit.MONTHS);

// Microseconds from specific time until now
long untilTime = localTime.until(LocalTime.now(), ChronoUnit.MICROS);

If the application needs to apply both date and time regularly, then the LocalDateTime class can be helpful, which merges the features presented until now in just one object.

TimeZone

The solutions showed so far are helpful for most of the date/time problems in an application. However, it can be necessary eventually to have one more information about the system hour: the time zone. One example of this is a social media server, which wants to show a relative post time for each user around the world. For cases like this, the Java Time API offers a ZonedDateTime class with all the characteristics discussed until now, adding a ZoneId parameter in some methods.

// Current system date, time and time-zone
ZonedDateTime zonedDateTime = ZonedDateTime.now();
// Current date and time from specific zone
zonedDateTime = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));

// Get all possibles ZoneId
Set<String> zones = ZoneId.getAvailableZoneIds();

// ZonedDateTime from LocalDateTime
zonedDateTime = ZonedDateTime.of(LocalDateTime.now(), ZoneId.of("Egypt"));
// ZonedDateTime from LocalDate and LocalTime
zonedDateTime = ZonedDateTime.of(LocalDate.now(), LocalTime.now(), ZoneId.of("UTC"));

Clock and Instant

The whole time package has its construction over the Clock and Instant classes, the first implements an interface between the JVM and the system clock, working with real-time updates and time-zone reference, being a substitute to the System.currentTimeMillis() or TimeZone.getDefault(). The Instant class, on the other hand, store an instantaneous point in time, counting the seconds with a long and an integer with the nanoseconds starting in the Java standard epoch of 1970-01-01T00:00:00Z. The whole package classes use these two as the basis to consult and store the system date but offering a higher level of abstraction.

The following code lines demonstrate some examples of the Clock and Instant classes and your relations with the LocalDateTime and ZoneDateTime classes.

// System Clock and convert to the UTC time-zone
Clock clock = Clock.systemUTC();
// System Clock and convert to system default time-zone
clock = Clock.systemDefaultZone();
// System Clock with specific time-zone
clock = Clock.system(ZoneId.of("Japan"))

// Using Clock to create a LocalDateTime instant
LocalDateTime localDateTime = LocalDateTime.now(clock);

// Instantaneous point in time
Instant instant = Instant.now();
// Instant point from a clock
instant = Instant.now(clock);

// Get ZoneDateTime from instant
ZonedDateTime zoneDateTime = instant.atZone(ZoneId.of("America/Costa_Rica"));

Other classes

The Java Time API has some extra features used internally and which is available to developers, allowing the management of the date with smaller classes. Year, YearMonth and MonthDay are samples of these classes. Its operations don't differ from LocalDate, but they have restrictions about the format and information stored for each one.

// Return current Year object
Year year = Year.now();
// Specific Year
year = Year.of(2035);
// Get LocalDate from day at the Year
LocalDate localDate = year.atDay(150);

// YearMonth object
YearMonth yearMonth = year.atMonth(Month.JULY);

These extra features can be helpful in some specific cases, saving the programmer to implement a personal class to fit your needs.

Conclusion

The Java SE 8 and the Time/Date API introduces a new approach to handle the date and time data in the Java Language. Before that, we have two other classes, util.Calendar and util.Date, where the two don't were thread-safe and don't handle time zone information, besides other obstacles.

The new API solves these problems and link the two main classes by the same mechanism, making it easier for the interaction between different objects. Bring more security for the programmer to handle this kind of data, without the need for additional logic implementation.

References

Java SE 8 Time Package documentation