The new Date/Time API was designed with the following principles:
The first classes to learn when using the new API are LocalDate, LocalTime and LocalDateTime, which is a pairing of the former classes:
LocalTime time = LocalTime.now();
LocalDate date = LocalDate.now();
LocalDateTime dt = LocalDateTime.of( date, time ); // You can also call LocalDateTime.now();
They are local in the sense that they represent date and time from the context of one observer, in contrast to time zones.
All the core classes in the new API are constructed by factory methods. When constructing a value through its fields, the factory is called of. When converting from another type, the factory is called from. There are also parse methods that take strings as parameters:
LocalDate ld1 = LocalDate.of(2014, Month.SEPTEMBER, 19);
LocalDate ld2 = LocalDate.ofEpochDay(1000);
LocalTime lt1 = LocalTime.of(14, 05);
LocalTime lt2 = LocalTime.parse("14:05:00");
You can use standard getters to obtain values from the classes:
int m = LocalDate.now().getDayOfMonth();
int y = LocalDate.now().getYear();
int h = LocalTime.now().getHour();
int min = LocalTime.now().getMinute();
You can also modify the object values by using the with methods instead of using setters (because the classes are immutable, which also means that you don't actually modify a class, a new one is returned):
LocalDateTime thePast = dt.withDayOfYear(90).withHour(21);
There are other methods to perform calculations:
LocalDateTime dt = dt.plusMinutes(10).plus(2, ChronoUnit.DAYS);
LocalDateTime dt = dt.minusYears(10);
An instant is a point of time counting from the first second of 1/1/1970, also known as epoch. Instants after the epoch have positive values, and earlier instants have negative values and a larger value is always later on the timeline than a smaller value.
The range of an instant requires the storage of a number larger than a long. To achieve this, the class stores a long representing epoch-seconds and an int representing nanosecond-of-second, which will always be between 0 and 999,999,999.
An Instant can be created in a similar way as a date or a time:
Instant now = Instant.now();
Instant epochNow = Instant.ofEpochSecond(1000000);
It also has get, plus and minus methods:
long s = now.getEpochSecond();
int n = now.getNano();
Instant twoSecondsAfter = now.plusSeconds(2);
Instant twoSecondsBefore = now.minusSeconds(2);
A period represents a value such as "1 months and 15 days", in contrast to the other classes that represent a point in time.
Here are some ways to create a period:
Period period = Period.of(1, 2, 3); // 1 year, 2 months, 3 days
Period periodTwoMonths = Period.ofMonths(2);
Period period20142015 = Period.between(LocalDate.of( 2014, Month.JANUARY, 1), LocalDate.of( 2015, Month.JANUARY, 1));
It also has get, plus and minus methods:
int y = period.getYears();
Period newPeriod = period.plusDays(2).minusMonths(1);
You can modify the values of dates using periods:
LocalDate newDate = date.plus(period);
A duration is similar to a period but its precision is based on hours, minutes, seconds, milliseconds.
A duration can be created using an amount of seconds or minutes or hours or by specifying start and end times:
Duration d2 = Duration.ofSeconds(10, 50); // 10 seconds and 50 nanoseconds
Duration d2 = Duration.between(LocalTime.NOON, LocalTime.MIDNIGHT);
It's also possible to perform normal plus, minus, and with operations on durations and also like periods, modify the value of a date or time using a duration.
Time zones are defined by their offset from Coordinated Universal Time (UTC) and correspond to a region in which the time is the same.
Time zones can be referred to by two identifiers: abbreviated, for example, "PLT" and longer, for example, "Europe/Paris". ZoneId is an identifier for a region:
ZoneId id = ZoneId.of("Europe/Paris");
ZoneOffset is the period of time representing a difference between Greenwich/UTC and a time zone.
ZoneOffset offset = ZoneOffset.of("-06:00");
ZonedDateTime is a date and time with a fully qualified time zone. You should use this class if you want to represent a date and time without relying on the context of a specific server.
ZonedDateTime zdt1 = ZonedDateTime.parse("2014-12-03T10:15:300[Europe/Paris]");//2014-12-03T10:15:300Z[Europe/Dublin]
ZonedDateTime zdt2 = ZonedDateTime.now(ZoneId.of("Europe/Paris"));
OffsetDateTime is an immutable representation of a date-time with an offset from UTC/Greenwich, for example '2000-12-31T10:15:30+01:00'.
OffsetDateTime, ZonedDateTime, and Instant all store an instant on the timeline to a nanosecond precision. Instant is the simplest, just representing the instant. OffsetDateTime adds to the instant the offset from UTC/Greenwich, which allows the local date-time to be obtained. ZonedDateTime adds full timezone data.
OffsetTime is a time with an offset from UTC/Greenwich in the ISO-8601 calendar system, such as '08:45:21+05:00'.
OffsetDateTime odt = OffsetDateTime.of(LocaDateTime.now(),ZoneOffset.of("-4")); //2015-05-22T23:42:20.101-06:00
OffsetTime ot = OffsetTime.ofInstant(Intant.now(),ZoneId.of("America/Los_Angeles")); //22:42:20.101-07:00
Clock gives us the ability to get the current date/time from the system clock with a specific timezone:
Clock defaultZone = Clock.systemDefaultZone();
Clock clock = Clock.system(ZoneId.of("Europe/Italy"));
java.time.format.DateTimeFormatter is the class for printing and parsing date-time objects.
This class works by using:
The date-time classes provide two methods - one for formatting, for example:
LocalDateTime dt = LocalDateTime.of( 2010, Month.JULY, 03, 09, 0, 30 );
String isoDateTime = dt.format(DateTimeFormatter.ISO_DATE_TIME);
And one for parsing, for example:
LocalDate dt = LocalDate.parse( "2014/09/19 14:05:12", DateTimeFormatter.ofPattern( "yyyy/MM/dd kk:mm:ss" ) );
The last example makes use of a pattern. Patterns are sequences of letters and symbols used to create a Formatter using the ofPattern(String)
and ofPattern(String, Locale)
methods.
Instant captures the current moment in time. They are useful for obtaining timestamps to a nanosecond precision.
Instant i = Instants.now();
Period represents an amount of time in years, months, and/or days. They are useful for adding/subtracting time to/from a date:
LocalDateTime today = LocalDateTime.now();
Period period = Period.ofDays(7);
LocalDateTime nextWeek = today.plus(period);
Duration represents an amount of time in hours, minutes, and/or seconds. Same concept as period but with time units:
LocalTime now = LocalDateTime.now();
Duration tenMinutes = Duration.ofMinutes(10);
LocalTime tenMinutesLater = now.plus(tenMinutes);
Period and Duration also have a between()
method to for determining elapsed time between dates (or time) objects:
LocalDate ld1 = LocalDate.parse("2015-05-23");
LocalDate ld2 = LocalDate.parse("2014-05-23");
Period timeBetween = Period.between(ld1,ld2); //Difference in years, months, days
Duration timeSpan = Duration.between(ld1,ld2); //Difference in hours, minutes, seconds
TemporalUnit is an interface that represents a unit of date-time, like years, months, days, hours, minutes and seconds. It doesn't represent the amount of the unit. Its implementation is the class ChronoUnit, which contains enum constants like:
And almost any other time unit you can imagine. It has some helpful methods like between()
. For example, if you need to find the number of years between two dates:
ChronoUnit.YEARS.between(date1, date2):