Java Time
There were many issues experienced by developers in prior versions of Java 8 such as;
- Date and Calendar Classes were not immutable
- They were not thread safe
- Lack of date time conversion methods
- 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