Using Date in Java

In any business application, at one time or another, you will need to represent dates or time. Either for business code or simply for logs. Mastering dates representation and concepts is crucial in the developer’s path. Let’s see how to use Date in Java.

Before Java 8, dates only support was by using java.util.Date. And for your business application, it’s bad. If you want to know why it’s bad in details, here’s a brilliant article about it. In short, java.util.Date only represents a timestamp, an instant of time. It is full of design flaws and for this was deprecated in Java 1.1, 23 years ago. As a result, a lot of initiative like Joda Time provided quality date replacements.

Since Java 8, multiple packages, under java.time, were introduced. In these packages we have :

  • lots of different abstractions of date and time (java.time.temporal),
  • classes made to handle time zones (java.time.zone),
  • some to handle date and time formatting (java.time.format), see ISO 8601 for norms on date formatting,
  • and also some alternatives calendaring systems such as the Japanese calendar (java.time.chrono.JapaneseChronology.java).

What does it look like

Let’s see what it looks like with a code example. There are many components to this API. But when seen in action, it’s actually simple.

Handle dates like a boss

Here we’re going to create the most used types: LocalTime, LocalDate, LocalDateTime and ZonedDateTime in a way that you’ll quickly understand the purpose of each type.

LocalTime time = LocalTime.parse("12:50:12");   // Following ISO parsing when no DateFormatter specified
LocalDate date = LocalDate.parse("2020-01-01"); // idem
ZoneId zone = ZoneId.of("UTC");
LocalDateTime localDateTime = LocalDateTime.of(date, time);
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, zone);
System.out.print(zonedDateTime.toString()); // prints "2020-01-01T12:50:12Z[UTC]"

It’s not the only way to build them, they have plenty of static method to create each type. See the doc here.

Here is a little cheat sheet of date format:

Date Format in Java, cheat sheet

Handle queries like a boss

Dates can be queried. It means that there is already a good bunch of method that can help you doing various operations on date. We use the query() method on a date, with a TemporalQuery as parameter.

TemporalQuery is a functional interface, which mean we can use a lambda expression inside our query. Let’s query our previous ZonedDateTime in order to figure out in which quarter of the year it is:

// zonedDateTime holds the date 2020-01-01T12:50:12Z[UTC]
Integer quarterOfYear = zonedDateTime.query(temporal -> (LocalDate.from(temporal).getMonthValue() / 3) + 1);
System.out.print(quarterOfYear); // prints "1"

/* ------------------- Other example ------------------- */
// zonedDateTime holds the date 2020-08-30T12:50:12Z[UTC]
Integer quarterOfYear = zonedDateTime.query(temporal -> (LocalDate.from(temporal).getMonthValue() / 3) + 1);
System.out.print(quarterOfYear); // prints "3"

Instead of using query(), you can use the queryFrom() method from your TemporalQuery object. But I don’t recommend this usage as it is more difficult to read than the query() way.

Handle date adjustment like a boss

We have seen how to create and query dates. Now, what if we need to do some processing and modify dates ? For this, we use the TemporalAdjuster functional interface and the with() method. It’s very similar to the previous example.

Let’s take our previous ZonedDateTime and use some common and useful TemporalAdjuster, pre-made into the TemporalAdjusters class (Note the plural).

/* ------------------- firstDayOfMonth example ------------------- */

// zonedDateTime holds the date 2020-08-30T12:50:12Z[UTC]
ZonedDateTime modified = zonedDateTime.with(TemporalAdjusters.firstDayOfMonth());
System.out.print(modified.toString()); // prints "2020-08-01T12:50:12Z[UTC]"


/* ------------------- firstDayOfYear example ------------------- */

// zonedDateTime holds the date 2020-08-30T12:50:12Z[UTC]
ZonedDateTime modified = zonedDateTime.with(TemporalAdjusters.firstDayOfYear());
System.out.print(modified.toString()); // prints "2020-01-01T12:50:12Z[UTC]"


/* ------------------- lastDayOfYear example ------------------- */

// zonedDateTime holds the date 2020-08-30T12:50:12Z[UTC]
ZonedDateTime modified = zonedDateTime.with(TemporalAdjusters.lastDayOfYear());
System.out.print(modified.toString()); // prints "2020-12-31T12:50:12Z[UTC]"

You can also create your own adjuster like we did with the query example.

You’ve seen examples on how to handle dates with the new java.time functionalities.

Be careful as a lot of java code still contains legacy java.date. These functionalities have been deprecated for a long date so if you find some in your code, consider refactoring. As seen in the example, the API is really easy to grasp and will avoid a lot of errors in your program.