1. Introducing the Date Time API

Introducing the Date Time API

Java's creators didn't like the situation with the Date and Calendar classes. They were good in their day, but times change. And something simple, powerful and reliable became necessary. And with the release of Java 8 (15 years after Calendar appeared), the Java Date Time API was introduced. It is a set of classes that should be able to solve every possible task dealing with time.

There were so many classes that they were split into several packages:

The java.time package is the base package for the Java Date Time API: it contains classes such as LocalDate, LocalTime, LocalDateTime, Instant, Period, and Duration. All objects of these classes are immutable, which means they cannot be changed after creation.

The java.time.format package contains classes for time formatting, i.e. converting times (and dates) to strings and vice versa. For example, it contains the versatile DateTimeFormatter class, which replaces the SimpleDateFormat class.

The java.time.zone package contains classes for working with time zones. It contains classes such as TimeZone and ZonedDateTime. If you're writing server code for clients located in different parts of the world, you will really need these classes.


2. LocalDate class

The first and most useful class from the Date Time API that we'll look at is the LocalDate class. As you can probably guess from its name, this class is designed to work with dates.

Objects of this class do not change after they are created, i.e. the LocalDate class is immutable. But this property adds simplicity and reliability to the class. Especially if several threads (threads of execution) are interacting with such an object at the same time.

To create a new LocalDate object, you need to use one of the static methods. Here is a list of the main ones.

Getting the current date

To get the current date, you need to use the static now() method. This is much easier than it seems:

LocalDate today = LocalDate.now();

Where today is a LocalDate variable, and LocalDate.now() is a call to the static now() method of the LocalDate class.

Example:

Code Console output
LocalDate today = LocalDate.now();
System.out.println("Today = " + today);

Today = 2019-02-22

Getting a date in a specific time zone

The LocalDate class also has a variation of the now(ZoneId) method that lets you get the current date in a specific time zone.

To do this, we need another class — the ZoneId class (java.time.ZoneId). It has an of() method that returns a ZoneId object given the name of the time zone.

To determine the current date in Shanghai, you need to write the following code:

Code Console output
ZoneId  timezone = ZoneId.of("Asia/Shanghai");
LocalDate today = LocalDate.now(timezone);
System.out.println("In Shanghai, now = " + today);


In Shanghai, now = 2019-02-22

You can find a list of the names of all the time zones on the Internet.


3. Getting a specific date

To get a LocalDate object that represents a specific date, you need to use the static of() method. Everything here is also very simple and clear:

LocalDate date = LocalDate.of(2019, Month.FEBRUARY, 22);

Where date is a LocalDate variable, and LocalDate.of() is a call to the static of() method of the LocalDate class.

Here we see the FEBRUARY constant of the Month class (java.time.Month) being used to specify February as the month.

You can also specific the month in the old fashioned way — using a number:

LocalDate date = LocalDate.of(2019, 2, 22);

Two? Instead of February? Does that mean the months are once again being numbered from one?

Yes, nearly 20 years after Java's creation, months have finally stopped being numbered from zero.

Example:

Code Console output
LocalDate today = LocalDate.of(2019, 2, 22);
System.out.println("Today = " + today);

Today = 2019-02-22

Getting a date by the index of the day

There's another interesting way to create a date: using the ofYearDay method, you can get a date based only on the number of the year and the index of the day in the year. Here's the general appearance:

LocalDate date = LocalDate.ofYearDay(year, day);

Where year is the number of the year and day is the index of the day in the year.

Example:

Code Console output
LocalDate today = LocalDate.ofYearDay(2019, 100);
System.out.println("Today = " + today);

Today = 2019-04-10

The 100th day of 2019 is April 10th.

Getting a Unix date

Do you recall that Date objects always stored time as the number of milliseconds since January 1, 1970? To ensure programmers wouldn't miss the good old days, the LocalDate class got an ofEpochDay() method, which returns the date calculated from the January 1, 1970. Here's the general appearance:

LocalDate date = LocalDate.ofEpochDay(day);

Where day is the number of days that have elapsed since January 1, 1970.

Example:

Code Console output
LocalDate today = LocalDate.ofEpochDay(1);
System.out.println("Today = " + today);

Today = 1970-01-02

4. Getting elements of a date

It is impossible to change LocalDate objects, but you can get individual elements of the stored date. LocalDate objects have several methods for this:

Method Description
int getYear()
Returns the year of a specific date
Month getMonth()
Returns the date's month: one of several constants
JANUARY, FEBRUARY, ...;
int getMonthValue()
Returns the index of the date's month. January == 1.
int getDayOfMonth()
Returns the index of the day of the month
int getDayOfYear()
Returns the day's index from the beginning of the year
DayOfWeek getDayOfWeek()
Returns the day of the week: one of several constants
MONDAY, TUESDAY, ...;
IsoEra getEra()
Returns the era: either BCE (Before Current Era) and CE (Current Era)

Example:

Code Console output
LocalDate today = LocalDate.now();
System.out.println(today.getYear());
System.out.println(today.getMonth());
System.out.println(today.getMonthValue());
System.out.println(today.getDayOfMonth());
System.out.println(today.getDayOfWeek());

2019
FEBRUARY
2
22
FRIDAY

5. Changing the date in a LocalDate object

The LocalDate class contains several methods that let you work with dates. The implementation of these methods is analogous to the methods of the String class: they do not change the existing LocalDate object, but instead return a new one with the desired data.

Here are the methods of the LocalDate class:

Method Description
plusDays(int days)
Adds a specified number of days to the date
plusWeeks(int weeks)
Adds weeks to the date
plusMonths(int months)
Adds months to the date
plusYears(int years)
Adds years to the date
minusDays(int days)
Subtracts days from the date
minusWeeks(int weeks)
Subtracts weeks from the date
minusMonths(int months)
Subtracts months from date
minusYears(int years)
Subtracts years from the date

Example:

Code Console output
LocalDate birthday = LocalDate.of(2019, 2, 28);
LocalDate nextBirthday = birthday.plusYears(1);
LocalDate firstBirthday = birthday.minusYears(30);

System.out.println(birthday);
System.out.println(nextBirthday);
System.out.println(firstBirthday);




2019-02-28
2020-02-28
1989-02-28

The birthday object whose methods we call does not change. Instead, its methods return new objects that contain the desired data.