A big part of the developer community had complained about Date and Calendar classes. The reasons were many such as hard to understand, hard to use, and not being flexible. Date class had become obsolete, and java docs suggested using Calendar class. And on top of all, date comparison was buggy.
Moving forward, Java 8 is expected to release the new Date and Time APIs/classes (JSR-310), called ThreeTen, which will change how you have been handling dates in Java. This A key part of this is providing a new API that is dramatically easier to use and less error prone.
It will provide some highly demanded features such as:
- All the core public classes are immutable and thread-safe
- Defined terminology and behavior that other areas in computing can adapt
1. Core Classes to Represent Date and Time
The new classes intended to replace Date class are LocalDate
, LocalTime
and LocalDateTime
.
1.1. LocalDate
The LocalDate class represents a date. There is no representation of a time or time zone.
LocalDate localDate = LocalDate.now();
System.out.println(localDate.getDayOfWeek().toString()); //WEDNESDAY
System.out.println(localDate.getDayOfMonth()); //15
System.out.println(localDate.getDayOfYear()); //135
System.out.println(localDate.isLeapYear()); //false
1.2. LocalTime
The LocalTime class represents a time. There is no representation of a date or time zone.
//LocalTime localTime = LocalTime.now(); //toString() in format 09:57:59.744
LocalTime localTime = LocalTime.of(12, 20);
System.out.println(localTime.toString()); //12:20
System.out.println(localTime.getHour()); //12
System.out.println(localTime.getMinute()); //20
System.out.println(localTime.getSecond()); //0
System.out.println(localTime.MIDNIGHT); //00:00
System.out.println(localTime.NOON); //12:00
1.3. LocalDateTime
The LocalDateTime class represents a date-time. There is no representation of a time zone. It represents the date and time in the current time zone.
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDateTime.toString()); //2013-05-15T10:01:14.911
System.out.println(localDateTime.getDayOfMonth()); //15
System.out.println(localDateTime.getHour()); //10
System.out.println(localDateTime.getNano()); //911000000
1.4. OffsetDateTime and ZonedDateTime
If you want to use the date functionality with timezone information, then the new API provides 2 classes similar to the above one i.e. OffsetDateTime and ZonedDateTime.
- OffsetDateTime represents the date-time with an offset from UTC/Greenwich in the ISO-8601 calendar system.
- ZonedDateTime represents the date-time with a time-zone in the ISO-8601 calendar system.
OffsetDateTime offsetDate = OffsetDateTime.now();
System.out.println(offsetDate); //2023-02-07T15:10:46.260589600+05:30
ZonedDateTime zonedDateTime = ZonedDateTime.now();
System.out.println(zonedDateTime); //2023-02-07T15:10:46.260589600+05:30[Asia/Calcutta]
2. Core Classes to Represent Timestamp and Duration
The new API has separate classes to denote the timestamp in the current timezone and in a specified timezone. We also have separate classes to denote the difference between the two dates in a consistent manner.
2.1. Instant
For representing the specific timestamp at any moment, we use Instant. The Instant
class represents an instant in time to an accuracy of nanoseconds. Operations on an Instant
include the comparison to another Instant
and adding or subtracting a duration.
Instant instant = Instant.now();
System.out.println(instant.toString()); //2013-05-15T05:20:08.145Z
System.out.println(instant.plus(Duration.ofMillis(5000)).toString()); //2013-05-15T05:20:13.145Z
System.out.println(instant.minus(Duration.ofMillis(5000)).toString()); //2013-05-15T05:20:03.145Z
System.out.println(instant.minusSeconds(10).toString()); //2013-05-15T05:19:58.145Z
2.2. Duration
The Duration class is a whole new concept brought first time in java language. It represents the time difference between two timestamps.
Duration duration = Duration.ofMillis(5000);
Duration duration = Duration.ofSeconds(60);
Duration duration = Duration.ofMinutes(10);
Duration duration = Duration.ofHours(2);
Duration duration = Duration.between(Instant.now(), Instant.now().plus(Duration.ofMinutes(10)));
Duration
deals with small units of time such as milliseconds, seconds, minutes and hours. They are more suitable for interacting with application code.
2.3. Period
To interact with humans, you need to get bigger durations presented with Period class.
Period period = Period.ofDays(6);
Period period = Period.ofMonths(6);
Period period = Period.between(LocalDate.now(), LocalDate.now().plusDays(60));
3. Utility Classes and Enums
The current Java SE platform uses int constants for months, day-of-week and am-pm etc. Now a lot of extra utility classes have been added that work on top of these enums. We are taking an example of such a class DayOfWeek. This class is a wrapper of day enums and can be used consistently with other classes.
Other such classes are Month
, MonthDay
, Year
, YearMonth
and many more.
//day-of-week to represent, from 1 (Monday) to 7 (Sunday)
System.out.println(DayOfWeek.of(2)); //TUESDAY
DayOfWeek day = DayOfWeek.FRIDAY;
System.out.println(day.getValue()); //5
LocalDate localDate = LocalDate.now();
System.out.println(localDate.with(DayOfWeek.MONDAY)); //2013-05-13 i.e. when was monday in current week ?
4. Date Adjusters
Date adjusters are another beautiful and useful addition to date-handling tools. It easily solves the problems like: How do you find the last day of the month? Or the next working day? Or a week on Tuesday?
LocalDate date = LocalDate.of(2013, Month.MAY, 15); //Today
LocalDate endOfMonth = date.with(TemporalAdjusters.lastDayOfMonth());
System.out.println(endOfMonth.toString()); //2013-05-31
LocalDate nextTue = date.with(TemporalAdjusters.next(DayOfWeek.TUESDAY));
System.out.println(nextTue.toString()); //2013-05-21
5. Fluent API
Creating date objects now can be done using builder pattern also. The builder pattern allows the object be built using individual parts. This is achieved using the methods prefixed by “at”.
//Builder pattern
OffsetDateTime offsetDateTime = Year.of(2013)
.atMonth(Month.MAY).atDay(15)
.atTime(0, 0)
.atOffset(ZoneOffset.of("+03:00"));
//factory method
OffsetDateTime date2 = OffsetDateTime.of(2013, 5, 15, 0, 0, 0, 0, ZoneOffset.of("+03:00"));
6. System Clock
A new class Clock is proposed in the new release. This simulates the system clock functionality.While doing unit testing, you are often required to test an API on future dates. For this, we had been forwarding the system clock for the next date, and then again restarting the server and testing the application.
Now, no need to do this. Use Clock
class to simulate this scenario.
Clock clock = Clock.systemDefaultZone();
System.out.println(clock); //SystemClock[Asia/Calcutta]
System.out.println(clock.instant().toString()); //2013-05-15T06:36:33.837Z
System.out.println(clock.getZone()); //Asia/Calcutta
Clock anotherClock = Clock.system(ZoneId.of("Europe/Tiraspol"));
System.out.println(anotherClock); //SystemClock[Europe/Tiraspol]
System.out.println(anotherClock.instant().toString()); //2013-05-15T06:36:33.857Z
System.out.println(anotherClock.getZone()); //Europe/Tiraspol
Clock forwardedClock = Clock.tick(anotherClock, Duration.ofSeconds(600));
System.out.println(forwardedClock.instant().toString()); //2013-05-15T06:30Z
7. Timezone
Timezone related handling is done by 3 major classes. These are ZoneOffset, TimeZone, ZoneRules.
- The
ZoneOffset
class represents a fixed offset from UTC in seconds. This is normally represented as a string of the format “±hh:mm”. - The
TimeZone
class represents the identifier for a region where specified time zone rules are defined. - The
ZoneRules
are the actual set of rules that define when the zone-offset changes.
System.out.println(ZoneRules.of(ZoneOffset.of("+02:00")).isDaylightSavings(Instant.now()));
System.out.println(ZoneRules.of(ZoneOffset.of("+02:00")).isFixedOffset());
8. Format a Date
Date formatting is supported via two classes, mainly i.e. DateTimeFormatterBuilder and DateTimeFormatter. DateTimeFormatterBuilder works on builder pattern to build custom patterns whereas DateTimeFormatter
provides necessary input in doing so.
DateTimeFormatterBuilder formatterBuilder = new DateTimeFormatterBuilder();
formatterBuilder.append(DateTimeFormatter.ISO_LOCAL_DATE_TIME).appendLiteral("-").appendZoneOrOffsetId();
DateTimeFormatter formatter = formatterBuilder.toFormatter();
System.out.println(formatter.format(ZonedDateTime.now()));
These are major changes that I was able to identify and work on.
Happy Learning !!