Java Time

thisara udayantha
6 min readApr 9, 2021

There were many issues experienced by developers in prior versions of Java 8 such as;

  1. Date and Calendar Classes were not immutable
  2. They were not thread safe
  3. Lack of date time conversion methods
  4. Unavailability of timezone translation methods

In order to solve those practical issues, some alternative libraries were popular among Java developers such as;

  • Joda-Time
  • Date4J
  • Apache Commons DateUtils
  • Project Thirteen

These alternatives were addressing the pitfalls in the language provided Date and Calendar, nevertheless Java language realize this is a handicap for the developers and they added a new package called java.time with the revealing of Java 8 to the general public.

There is a distinct separation between classes which are intentionally created for timezone conversions and general regional specific usage with date time or timestamp. The classes could be classified as below;

And all the timezone specific and local date-time classes within time package are independent and they inherit only from Object class.

java.lang.Object

  • java.time.LocalDate
  • java.time.LocalTime
  • java.time.LocalDateTime
  • java.time.OffsetDateTime
  • java.time.OffsetTime
  • java.time.Duration
  • java.time.Period
  • java.time.Instant
  • java.time.ZonedDateTime
  • java.time.ZoneId

Next, let’s elaborate some useful implementations of java.time package classes;

LocalDate

LocalDate with Year, Month and Date

This defaults to ISO 8601 date format which is ‘yyyy-MM-dd’.

LocalDate localDate = LocalDate.of(2021, 03, 20);print("localDate : " + localDate);

localDate : 2021–03–20

LocalDate Parse with Date in String Format

LocalDate localDateParsed = LocalDate.parse("2021-03-20");print("localDateParsed : " + localDateParsed);

localDateParsed : 2021–03–20

Format LocalDate into Custom Pattern

LocalDate localDate = LocalDate.of(2021, 03, 20);String localDateFormatted = localDate.format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));print("localDateFormatted : " + localDateFormatted);

localDateFormatted : 2021/03/20

Date After Specific Number of Days

There are multiple options available to get this with the same result.

LocalDate localDate = LocalDate.of(2021, 03, 20);LocalDate dateInNextWeek = localDate.plus(7, ChronoUnit.DAYS);
// or
LocalDate dateInNextWeek = localDate.plus(Period.ofDays(7));
// or
LocalDate dateInNextWeek = localDate.plusDays(7);
print("dateInNextWeek : " + dateInNextWeek);

dateInNextWeek : 2021–03–27

Difference Between Two Dates

LocalDate localDate = LocalDate.of(2021, 03, 20);LocalDate dateInNextWeek = localDate.plusDays(7);int dateDifference = Period.between(localDate, dateInNextWeek).getDays(); 
//or
long dateDifference = ChronoUnit.DAYS.between(localDate, dateInNextWeek);
print("dateDifference : " + dateDifference);

dateDifference : 7

Date Comparison

LocalDate startDate = LocalDate.parse("2021-03-20");
LocalDate endDate = LocalDate.parse("2021-04-20");

boolean isBeforeDate = startDate.isBefore(endDate);
boolean isAfterDate = startDate.isAfter(endDate);
print("startDate : " + startDate + " is-before, endDate : " + endDate + " ? " + isBeforeDate);
print("startDate : " + startDate + " is-after, endDate : " + endDate + " ? " + isAfterDate);

startDate : 2021–03–20 is-before, endDate : 2021–04–20 ? true
startDate : 2021–03–20 is-after, endDate : 2021–04–20 ? false

Get Specific Dates

LocalDate localDate = LocalDate.of(2021, 03, 20);LocalDate firstDayOfMonth = localDate.with(TemporalAdjusters.firstDayOfMonth());
LocalDate lastDayOfMonth = localDate.with(TemporalAdjusters.lastDayOfMonth());
print("firstDayOfMonth : " + firstDayOfMonth);
print("lastDayOfMonth : " + lastDayOfMonth);

firstDayOfMonth : 2021–03–01
lastDayOfMonth : 2021–03–31

LocalTime

LocalTime with Hour, Minute, Second and Nano of the second

LocalTime localTime = LocalTime.of(9, 30, 45, 50);print("localTime : " + localTime);

localTime : 09:30:45.000000050

LocalTime Parse with Time in String Format

LocalTime localTimeParsed = LocalTime.parse("09:30");print("localTimeParsed : " + localTimeParsed);

localTimeParsed : 09:30

LocalTime Format into Custom Pattern

LocalTime localTime = LocalTime.of(9, 30, 45, 50);String localTimeformatted = localTime.format(DateTimeFormatter.ofPattern("hh:mm:ss"));print("localTimeformatted : " + localTimeformatted);

localTimeformatted : 09:30:45

Time After Specific Time Period

LocalTime localTime = LocalTime.of(9, 30, 45, 50);LocalTime timeAtNextInterval = localTime.plus(Duration.ofSeconds(30));
// or
LocalTime timeAtNextInterval = localTime.plus(30, ChronoUnit.SECONDS);
// or
LocalTime timeAtNextInterval = localTime.plusSeconds(30);
print("timeAtNextInterval : " + timeAtNextInterval);

timeAtNextInterval : 09:31:15.000000050

Difference Between Time Instants

LocalTime localTime = LocalTime.of(9, 30, 45, 50);LocalTime timeAtNextInterval = localTime.plus(Duration.ofSeconds(30));long intervalDiff = ChronoUnit.SECONDS.between(localTime, timeAtNextInterval);print("intervalDiff : " + intervalDiff);

intervalDiff : 30

Compare Two Time Instances

LocalTime startTime = LocalTime.parse("09:30");
LocalTime endTime = LocalTime.parse("07:30");
boolean isBefore = startTime.isBefore(endTime);
boolean isAfter = startTime.isAfter(endTime);
print("startTime : " + startTime + " is-before, endTime : " + endTime + " ? " + isBefore);
print("startTime : " + startTime + " is-after, endTime : " + endTime + " ? " + isAfter);

startTime : 09:30 is-before, endTime : 07:30 ? false
startTime : 09:30 is-after, endTime : 07:30 ? true

LocalDateTime

With Year, Month, Date and Time

LocalDateTime localDateTime = LocalDateTime.of(2021, Month.MARCH, 27, 9, 30);print("localDateTime : " + localDateTime);

localDateTime : 2021–03–27T09:30

Parse From a Formatted String

LocalDateTime localDateTimeParsed = LocalDateTime.parse("2021-03-20T09:30:00");print("localDateTimeParsed : " + localDateTimeParsed);

localDateTimeParsed : 2021–03–20T09:30

Format into Custom Format

LocalDateTime localDateTime = LocalDateTime.of(2021, Month.MARCH, 27, 9, 30);String localDateTimeFormatted = localDateTime.format(DateTimeFormatter.ofPattern("yyyy/MM/dd hh:mm:ss"));print("localDateTimeFormatted : " + localDateTimeFormatted);

localDateTimeFormatted : 2021/03/27 09:30:00

Format into ISO Date

LocalDateTime localDateTime = LocalDateTime.of(2021, Month.MARCH, 27, 9, 30);String localISODate = localDateTime.format(DateTimeFormatter.ISO_DATE);print("localISODate : " + localISODate);

localISODate : 2021–03–27

Format into Local

LocalDateTime localDateTime = LocalDateTime.of(2021, Month.MARCH, 27, 9, 30);String ukDateTimeFormat = localDateTime.format(DateTimeFormatter
.ofLocalizedDateTime(FormatStyle.MEDIUM)
.withLocale(Locale.UK));
print("ukDateTimeFormat : " + ukDateTimeFormat);

ukDateTimeFormat : 27 Mar 2021, 09:30:00

Get Specific Date-Time

LocalDateTime localDateTime = LocalDateTime.of(2021, Month.MARCH, 27, 9, 30);LocalDateTime dateInNextYear = localDateTime.plus(1, ChronoUnit.YEARS);DayOfWeek dayOfWeek = dateInNextYear.getDayOfWeek();print("dateInNextYear : " + dateInNextYear + " / dayOfWeek : " + dayOfWeek );

dateInNextYear : 2022–03–27T09:30 / dayOfWeek : SUNDAY

ZonedDateTime

This class does not have any hierarchical relationship with LocalDateTime and dedicated for date-time representation with specific timezone information.

Get Current Zone Timestamp

ZonedDateTime zonedDateTimeNow = ZonedDateTime.now();print("zonedDateTimeNow : " + zonedDateTimeNow);

zonedDateTimeNow : 2021–04–08T19:42:14.233656+05:30[Asia/Colombo]

Get Different Zone Timestamp

ZonedDateTime zonedDateTimeDenver = ZonedDateTime.ofInstant(Instant.now(), ZoneId.of("America/Denver"));
// or
ZonedDateTime zonedDateTimeDenver = ZonedDateTime.now(ZoneId.of("America/Denver"));
print("zonedDateTimeDenver : " + zonedDateTimeDenver);

zonedDateTimeDenver : 2021–04–08T08:12:14.233751–06:00[America/Denver]

LocalDateTime to Different Zone

LocalDateTime localDateTime = LocalDateTime.now();ZoneId zoneId = ZoneId.of("Europe/Paris");ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, zoneId);print("zonedDateTime : " + zonedDateTime);

zonedDateTime : 2021–04–08T20:28:16.306180+02:00[Europe/Paris]

Compare Different Timezones

LocalDateTime localDateTime = LocalDateTime.of(2021, Month.MARCH, 27, 9, 30);ZoneId zoneId = ZoneId.of("Europe/Paris");
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, zoneId);
ZonedDateTime zonedDateTimeNow = ZonedDateTime.now();boolean isBeforeTime = zonedDateTime.isBefore(zonedDateTimeNow);print("zonedDateTime : " + zonedDateTime + " is-before, zonedDateTimeNow : "+ zonedDateTimeNow + " ? " + isBeforeTime);

zonedDateTime : 2021–03–27T09:30+01:00[Europe/Paris] is-before, zonedDateTimeNow : 2021–04–08T19:42:14.233656+05:30[Asia/Colombo] ? true

Get All Supported Timezones

Set<String> zoneIds = ZoneId.getAvailableZoneIds();

for(String zone : zoneIds) {
print("zone : " + zone);
}

zone : America/Virgin
zone : America/Pangnirtung
zone : Pacific/Noumea
zone : America/Argentina/San_Juan
zone : Australia/Darwin

Sample of time zone list output, and there will more getting printed when you execute the above code.

OffsetDateTime

There are few basic similarities and differences between OffsetDateTime and ZonedDateTime as listed below;

  • Both captures date-time to the precision of nano seconds.
  • ZonedDateTime is fully aware of DST adjustments, however in OffsetDateTime you will need to set the offset manually.
  • ZonedDateTime controls the offsets by itself and not able to adjust intentionally.
  • Act as a detailed user object since the ZoneDateTime contains all date-time related data including timezone and seconds up to the precision of nano seconds.
  • Although OffsetDateTime capture date-time without the timezone information, but the offset from UTC which is also known as the GMT.
  • OffsetDateTime is ideal as a data-store representation of date-time since it is more query friendly.

Define Date with an Offset

ZoneOffset offset = ZoneOffset.of("-07:00");OffsetDateTime offsetDateTime = OffsetDateTime.of(LocalDateTime.of(2021, Month.MARCH, 27, 9, 30), offset);print("offsetDateTime : " + offsetDateTime);

offsetDateTime : 2021–03–27T09:30–07:00

Get Current Date Time

As Instant

This will return the current UTC time.

Instant nowInstant = Instant.now();print("nowInstant : " + nowInstant);

nowInstant : 2021–04–08T15:01:51.119492Z

As LocalDateTime

This will return current date time without any timezone information.

LocalDateTime localDateTimeNow = LocalDateTime.now();print("localDateTimeNow : " + localDateTimeNow);

localDateTimeNow : 2021–04–08T20:32:13.227212

As ZonedDateTime

This will return the date-time with full information including the timezone.

ZonedDateTime zonedDateTimeNow = ZonedDateTime.now();print("zonedDateTimeNow : " + zonedDateTimeNow);

zonedDateTimeNow : 2021–04–08T20:32:31.689008+05:30[Asia/Colombo]

EPOCH / Unix Time

This is the time elapsed form 1/1/1970 which is 1970–01–01T00:00:00Z in ISO 8601 standard. This is also known as the Unix 0 time.

ZoneId zone = ZoneId.of("Europe/Berlin");
ZonedDateTime zonedDateTime = ZonedDateTime.now(zone);
long epochSeconds = zonedDateTime.toEpochSecond();print("epochSeconds : " + epochSeconds);

epochSeconds : 1617894177

Legacy Date and Calendar to Java8 Time

Calendar calendar = Calendar.getInstance();calendar.set(Calendar.MONTH, 02);
calendar.set(Calendar.DATE, 20);
calendar.set(Calendar.YEAR, 2021);
Date date = calendar.getTime();

LocalDateTime colomboTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.of("Asia/Colombo"));
LocalDateTime parisTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.of("Europe/Paris"));
print("colomboTime : " + colomboTime.toString());
print("parisTime : " + parisTime.toString());

colomboTime : 2021–03–20T20:33:37.711
parisTime : 2021–03–20T16:03:37.711

print(message) Method Implementation

public void print(String text) {
System.out.println(text);
}

Demo : https://bitbucket.org/thisara_udaya/java-time/

Practical Usage of Java Time : https://www.youtube.com/watch?v=poO-_V339mY

References :

[1] https://docs.oracle.com/javase/8/docs/api/java/time/package-tree.html

[2] https://docs.oracle.com/javase/tutorial/datetime/iso/overview.html

--

--