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.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.
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:
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.
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"));
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
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
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.
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
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
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
Instant classes and your relations with the
// 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"));
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.
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.
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.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.