Introduction to the Java 8 Date Time API
Java 8 introduced a new API for Date and Time. In this post, we will cover some of the features of the Java 8 Date Time API.
Java 1.0 introduced support for date and time using java.util.Date class.This API contains a lot of issues including not representing the date as a human-readable date but point in time with milliseconds.We will cover some of the issues or drawbacks of the existing Date API which made way for the Java 8 Date Time API.
1. Issues with the Existing Date Time API
- API Design – Initial Date class introduced in Java 1.0 was not a true representation of the date but a point in time with milliseconds as precision. Calander API introduced as a replacement was poorly designed and lead to confusion in day to day use.
- Thread Safety – The Date and Calander classes are not thread-safe.None of the instance methods are synchronized, and none of the instance fields are volatile, even get method can cause an instance of these classes as Mutable. A developer needs to ensure thread safety in case they are using these classes.
- Usability – Most of the methods provided by Java before Java 8 Date Time API were lacking readability and needs a more clear understanding of the underlying working of the code before using it.
Due to all these designs flaws and inconsistencies, most of the enterprise applications were forced to use third party solution like Joda-Time etc. To resolve all these issues, Java 8 introduced a brand new Date and Time API which is integrate many of the Joda-Time API features.
2. LocalDate, LocalTime and LocalDateTime
LocalDate, LocalTime, and LocaleDateTime are the most commonly used classes in the new Date API. These classes provide information independent of time zone i.e we do not need to worry about the time zone.
2.1 Working with LocalDate
LocalDate represents date without time zone in ISO format. This is one of the most commonly used classes in the new Date API.An instance of this class is immutable and represents date without information of the time and timezone.
LocalDate provides multiple utility methods to create an instance of this class. We can use of static factory method of the LocalDate class to create an instance of this class.
LocalDate date = LocalDate.of(2018, 01,8); //2018-01-08
Above code will represent the LocalDate for 8 January 2018. LocalDate instance provides a number of different methods which can be used for the most common values required while working to Date. We will cover some of the methods in this section.
LocalDate date = LocalDate.of(2018, 01,8);
int year = date.getYear(); //2018.
boolean isLeap = date.isLeapYear(); //f alse, 2018 is not Leap Year
int day = date.getDayOfMonth(); // 8
DayOfWeek dayOfWeek =date.getDayOfWeek(); //MONDAY
Month month =date.getMonth(); //JANUARY
int monthLength = date.lengthOfMonth(); //31
int daysOfYear = date.getDayOfYear(); // 8
We can use
LocalDate.now() factory method to obtain current date based on the system clock.
LocalDate systemDate = LocalDate.now(); //2018-01-08
LocalDate provides other utility methods to get a different kind of information. We will cover different operations that can be performed on the LocalDate object in other section of this post.
2.2 Working with LocalTime
LocalTime represents a time of the day (e.g 20:22: 12) without time zone and date.Like LocalDate, we can get an instance of LocalTime by using the static factory method.
LocalTime time = LocalTime.of(20, 45); //20:45
LocalTime time = LocalTime.of(20, 45, 12); //20:45 : 12
LocalTime class provides numbers of utility method to get information from the LocalTime instance.
LocalTime time = LocalTime.of(20, 45, 34); //20:45:34
int hour = time.getHour(); //20
int minutes = time.getMinute(); //45
int seconds = time.getSecond(); //34
To get time zone independent current LocalTime based on the system clock, we can use LocalTime.now() factory method.
LocalTime systemTime = LocalTime.now(); //20:49:35.509403
We can also create an instance of LocalTime by parsing String using LocalTime.parse() method
LocalTime systemTime = LocalTime.parse("15:45:45"); //15:45:45
2.3 Working with LocalDateTime
LocalDateTime is the combination of LocalDate and LocalTime. LocalDateTime represents date and time without time zone. We can create an instance of the LocalDateTime class by using now method or we can combine date and time instance to create the LocalDateTime object.
LocalDateTime localDateTime = LocalDateTime.of(2018, Month.JANUARY, 8, 21, 26, 12); //2018-01-08T21:26:12
LocalDate date= LocalDate.now();
LocalTime time = LocalTime.now();
LocalDateTime combieDataIssue = LocalDateTime.of(date,time); //2018-01-08T21:30:03.663603
LocalDateTime ldt = date.atTime(time); //2018-01-08T21:41:50.068417
LocalDateTime ldt1 = time.atDate(date); //2018-01-08T21:41:50.068417
3. Period and Duration
Use Duration class to represent time in seconds and nanoseconds and Period for time in years, months and days.
Duration is the time-based amount of time (e.g 12.4 seconds etc), here are some of the example for Duration
Duration twoMinutes = Duration.ofMinutes(3);
Duration duration = Duration.of(3, ChronoUnit.MINUTES);
LocalDateTime localDateTime = LocalDateTime.now();
LocalDateTime localDateTime1 =LocalDateTime.of(2018, Month.JUNE, 5, 10, 15, 45);
Duration duration1 = Duration.between(localDateTime1, localDateTime);
A date-based amount of time in the ISO calendar system.The period class can be used to modify a value for a given date or to find the difference between dates. Let’s take an example to understand how this can be used.
LocalDate initialDate= LocalDate.of(2017, 10, 11);
Use period class to get useful information from the 2 date instances.
Period days = Period.ofDays(4);
Period weeks = Period.ofWeeks(3);
LocalDate initialDate= LocalDate.of(2017, 10, 11);
LocalDate finalDate = LocalDate.of(2017, 11, 15);
int dayDuration = Period.between(initialDate, finalDate).getDays(); //4
int monthDuration = Period.between(finalDate,initialDate).getMonths(); // -1
4. Modify Dates Instance
One of the main features of the Java 8 Date Time API is thread safety and most of the classes we discussed are immutable.In certain cases, we might need we need a new instance of the give LocaleDate instance to work with.
To create a new object for the given LocalDate, we can use one of it’s withAttribute or more generic with a method.
LocalDate currentDate = LocalDate.now(); //current system date
LocalDate withYearDate= currentDate.withYear(2017); //Returns a copy of this date with the year altered //2017-01-09
LocalDate daysOfMonth = withYearDate.withDayOfMonth(12); // Returns a copy of this date with the day-of-month altered // 2017-01-12
These methods return a new object without keeping original LocalDate instance unchanged.
5. Manipulate Dates
New Java 8 Date Time API provides convenient ways to manipulate LocalDate instance. We can perform add, subtract on given Date instance.
LocalDate date = LocalDate.of(2017, 8, 23);
LocalDate date1 = date.plus(1, ChronoUnit.DAYS); // 2017-08-24
LocalDate date2 = date1.plusWeeks(1); // 2017-08-31 , one week added to date
LocalDate addYear = date2.plusYears(2); // 2019-08-31 , added 2 years
LocalDate minusYear = date2.minusYears(4); // 2013-08-31
LocalDate fromYear = minusYear.from(ZonedDateTime.now());
Please note that like
withAttribute methods defined in the earlier section, These methods return a new Object with modified attributes.
6. Parsing Dates
Before Java 8 parsing and formatting of Date object were not very easy. Java 8 new java.time.format package provides a lot of helpful methods to format or parse date easily.
DateTimeFormatter is one of the most important class under this package. We can use parse() method of the LocalDate instance to format given date instance.
LocalDate date = LocalDate.of(2011, 12, 17);
String formattedDate = date.format(DateTimeFormatter.BASIC_ISO_DATE); // 20111217
Use DateTimeFormatter for converting String to the LocalDate instance.
LocalDate stringFormattedDate = LocalDate.parse("20161217", DateTimeFormatter.BASIC_ISO_DATE); // 2016-12-17
LocalDate date1 = LocalDate.parse("2016-08-17", DateTimeFormatter.ISO_LOCAL_DATE); // 2016-08-17
DateTimeFormatter provides a number of formatter to work with, however,
- what are the option if we want to format a date for which we do not have formatter provided by DateTimeFormatter class.
The DateTimeFormatter class provides a static factory method for creating custom formatter.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
LocalDate currentDate = LocalDate.now(); // output : 2018-01-09
String formattedDate1 = currentDate.format(formatter); // output : 09/01/2018 in
LocalDate newDate = LocalDate.parse(formattedDate,formatter);
So we did few things in above example of created new LocalDate instance based on new formatter.
- We created DateTimeFormatter for dd/MM/yyyy format.
- We created String representation of the LocalDate instance.
- Used parse method provided by LocalDate class to create a new instance with required format.
If you are looking for Local based formatter, use the overloaded method of DateTimeFormatter by passing Local as an additional parameter.
DateTimeFormatter japaneseFormatter = DateTimeFormatter.ofPattern("M'月' yyyy'年'", Locale.JAPANESE);
String newFormatter = currentDate.format(japaneseFormatter); // output : 1月 2018年
LocalDate localDate = LocalDate.parse(formattedDate1,formatter);
This is numbers of benefits of using this new formatter.
- This is thread safe as compare to old DateFormat class.
- We can use the single instance of this formatter across multiple threads.
The parse() method can throw DateTimeParseException in case it is not able to parse String to a valid LocalDate or LocalTime instance.
6.1 Using DateTimeFormatterBuilder
New Java Date and Time API provide DateTimeFormatterBuilder class to create complex formatter.
DateTimeFormatter builder = new DateTimeFormatterBuilder()
.appendLiteral("Day of Month is :")
.appendLiteral(", Month is :")
.appendLiteral(", Year is : ")
.appendLiteral(", Time is :")
LocalDateTime localDateTime = LocalDateTime.now();
String date = localDateTime.format(builder);
Current Day is :9, Month is :1, Year is : 2018, Time is :21:16
7. Java Date Time API Features
We covered some of the basic features of Java 8 Date and Time API. There are numbers of features improvement this new API brings in, here are some of the most important features of new API.
- Most of the classes provided by new API are immutable which is more in line with functional programming introduced with Java 8.
- Better readability, think about Calander.getInstance() method as compare to LocalDate.now() or LocalTime().
- The new API uses immutable objects, which makes it thread safe.
In this article, we covered Java 8 Date Time API. We covered different features and improvement introduced by Java Date and Time API. This API is a complete replacement of the old Java API and integrate many of the features of Joda-Time API.