>> Monday, July 15, 2013
I started to experience the Java 8 new APIs (still Early Access at the moment of writing this post) and the first thing I looked into was the new date and time API (JSR 310). As there is much to cover in this new long awaited API I think it worth few posts with some examples. This post would be the first in a series, starting with some basic classes of the package: Instant, LocalDate, LocalTime, and LocalDateTime.
Instant (java.time.Instant)Probably the best place to start with the java.time package is the Instant class. An Instant represents a point in time (similar to java.util.Date) with nanoseconds precision (unlike the old Date which has milliseconds precision). Representing a point in time using nanoseconds precision requires more space than a Long can provide, therefore the internal representation is composed of two Long fields, the first holds the number of seconds since (or before) the standard Java epoch and the other the number of nanoseconds of the last seconds (so never larger than 999,999,999). Let's start with obtaining an Instant instance and print its value:
// Get the current time Instant instant = Instant.now(); // Output format is ISO-8601 System.out.println(instant);
Instant.toString() returns a ISO8601 formatted string (such as: '2013-06-25T16:22:52.966Z'), a much more logical choice than the one used by the old Date class. Here are some other ways to create Instants:
// Convert a java.util.Date into an Instant Instant instant = Instant.ofEpochMilli(new Date().getTime()); // Create from a String instant = Instant.parse("1995-10-23T10:12:35Z");
The second example above creates an Instant by parsing a String, this string must by a valid representation of a UTC Instant (NB: Instant is a point of time, it doesn't store any TimeZone information and as such it supports only UTC formatted strings). Instant API provides some useful methods to allow calculations using Instants and other classes in the package, below is a first example:
// Adding 5 hours and 4 minutes to an Instant instant.plus(Duration.ofHours(5).plusMinutes(4));
How many instances of java.time.Instant are used in the example above? Two. The java.time package is planned to be thread safe and as such most of its classes are immutable, Instant is not an exception to that rule and as such the plus() method creates a new instance.
Instant instant1 = instant.plus(Duration.ofHours(5).plusMinutes(4)); System.out.println("Instant is immutable, so instant==instant returns: " + (instant == instant1)); The output would be: Instant is immutable, so instant==instant returns: false
Here are few more examples of Instant calculations:
// Substract 5 days of an instant instant.minus(5, ChronoUnit.DAYS); // Option 1 instant.minus(Duration.ofDays(5)); // Option 2 // How many minutes are between to Instants? long diffAsMinutes = instant.periodUntil(instant1, ChronoUnit.MINUTES); // Option 1 long diffAsMinutes = ChronoUnit.MINUTES.between(instant, instant1); // Option 2
Instants are Comparable which means they can be used in any place a Comparable is expected (such as collections). Instant also provides the isAfter() and isBefore() methods which can make a more readable code:
// Compare the two System.out.format("instant1.compareTo(instant)=%d.%n", instant1.compareTo(instant)); // We can check to see which Instant is before/after the other System.out.format("instant1.isAfter(instant)=%b, instant1.isBefore(instant)=%b.%n", instant1.isAfter(instant), instant1.isBefore(instant)); The output would be: instant1.compareTo(instant)=1. instant1.isAfter(instant)=true, instant1.isBefore(instant)=false.
LocalDate and LocalTimeLocalDate represents a date without a time zone, such as 1-1-2000. LocalTime represents time without a time zone, such as 04:44:59.12 - unlike Instant which is an offset from the Java epoch and as such can be calculated into a precise point of time these two are just date or time without any relation to the epoch - a human readable date and time. There are several ways to obtain LocalTime and LocalDate instances, here are few:
LocalDate localDate = LocalDate.now(); localDate = LocalDate.ofYearDay(2005, 86); // The 86th day of 2005 (27-Mar-2005) localDate = LocalDate.of(2013, Month.AUGUST, 10); //10th of Aug 2013 LocalTime localTime = LocalTime.of(22, 33); //10:33 PM localTime = LocalTime.now(); localTime = LocalTime.ofSecondOfDay(4503); // The 4,503 second in a day (1:15:30 AM)
LocalDate and Local time follow the same general concept of multithreading as Instant does - and as such their instances are immutable. LocalDate and LocalTime have calculation and comparison methods similar to the ones Instant has (some of the methods are defined by the java.time.temporal.Temporal interface which implemented by all of these classes):
LocalDate localDate1 = localDate.plus(5, ChronoUnit.HOURS); localDate.isBefore(localDate1);
LocalDateTimeThe last important player in the simple date and time classes is LocalDateTime - this is a combination of LocalDate and LocalTime representing a date and the time within that date, again no time zone. LocalDateTime seems to be very similar to Instant, a reminder: "an Instant is point in time without time zone” and one could say that a point in time is nothing more than a date and time within that date. But there is a difference: LocalDateTime is not a point on the time line as Instant is, LocalDateTime is just a date and time as a person would write on a note. Consider the following example: two persons which were born at 11am, July the 2nd 2013. The first was born in the UK while the second in California. If we ask any of them for their birth date it will look that they were born on the same time (this is the LocalDateTime) but if we align the dates on the timeline (using Instant) we will find out that the one born in California is few hours younger than the one born in the UK (NB: to create the appropriate Instant we have to convert the time to UTC, this is where the difference lays). Beside of that LocalDateTime behaves very similar to the other classes illustrated above:
LocalDateTime localDateTime = LocalDateTime.now(); // Jump to 25 hours and 3 minutes into the future LocalDateTime inTheFuture = localDateTime.plusHours(25).plusMinutes(3); // We could do the same on localTime or localDate System.out.println(localDateTime.toLocalTime().plusHours(25).plusMinutes(3)); System.out.println(localDateTime.toLocalDate().plusMonths(2)); // We could also use TemportalAmount (in this case a Duration and Period) System.out.println(localDateTime.toLocalTime().plus(Duration.ofHours(25).plusMinutes(3))); System.out.println(localDateTime.toLocalDate().plus(Period.ofMonths(2)));