New package java.time that was introduced in Java 8 has surely made representation of date & time more closer to real world. Also the representation is more exact & without unwanted information. Lets explore in depth.
How do we really refer date, time & timezone in real world?
Lets take few examples to understand what do we mean when we talk about different dates, times & timezones.
- Generally when we tell someone our birth date, we tell them – day, month & year. We generally never mention time or timezone etc.
- So logically the object representation for birthday should ideally only have day, month & year.
- Store opening & closing times
- Generally when we talk about store opening & closing hours, we only refer to hour, minutes (may be seconds!). We do not mention date, month, year here as it doesn’t make sense here. Its a particular time on all working days.
- So logically the object representation should only have hour, minutes (optionally seconds)
- Question – Which is the next leap year?
- Answer to this question only requires year & nothing else.
- So logical representation of this answer must only have year & nothing else.
- Happy New Year Fireworks
- Happy new year mid night moment (or fireworks start time) happens at different moments around the world.
- Some countries have it early like Australia & other countries have it little later like USA. But everyone have new year event at 1st January 2019, 00:00:00 in their local date & time.
- So logically here we can either just mention new year as 1st January 2019 00 hours, 00 minutes 00 seconds. Or some might prefer to add timezone to be more accurate. So representation have day, month, year, hour, minute, seconds (and timezone if need to be specific).
- ECG/EKG graph of heart
- If we are creating software to record ECG/EKG of heart against “time“, then none of the human understandable information like date or time or timezone makes sense.
- Even though we are going to record heart activity against time, it won’t make sense to record it like 3mV at 28 December 2018 09:00:00 PM. Here time is more graphical than human readable date/time.
- So for such cases we need something completely different than human readable time like machine time etc.
Looking at above several examples, its pretty clear that representation of all such info with single class that holds all information i.e. year, month, day, hour, minute, and second might not be logically justifying.
How Java 8 helps represent date/time like real world?
Below table gives details of how Java 8 classes from java.time package helps represent real world data. In each example you can see that the classes used only represent expected information & no unwanted information.
|What to represent?||Example||Class to represent|
|Only Year||Next leap year||java.time.Year
2020 is leap year? true
|Only Month||Start of fall season i.e. September||java.time.Month (Enum)
Start of fall is SEPTEMBER
|Only Day of month||Valentine’s Day i.e 14’th Feb||java.time.MonthDay
Valentine's Day is on --02-14
|Only Day of week||Non working day i.e. Sunday||java.time.DayOfWeek (Enum)
SUNDAY is non working day
|Only Year, Month & Day||Birthday ex: 10 January 1981||java.time.LocalDate
Tom's birthday is on 1981-01-10
|Only Hour, Minute & Seconds||Store opening time like 09:00:00 AM||java.time.LocalTime
Store opening time is 09:00
|Only Year, Month, Day, Hour, Minute & Seconds||Happy New Year ex: 1 January 2019, 00:00:00 AM||java.time.LocalDateTime
Fireworks start at 2019-01-01T00:00
|Machine time or particular instance in time||ECG/EKG graph of heart||java.time.Instant
But wait, where’s time zone?
In general, we represent timezone in two ways
- By the name of time zone like “America/Los_Angeles”, “Asia/Kolkata” etc.
- By the offset from UTC/Greenwich like “GMT-8”, “UTC+05:30” etc.
Java now provides same analogy using classes
- By the name – java.time.ZonedDateTime & java.time.ZoneId
- By the offset from UTC – java.time.OffsetDateTime & java.time.ZoneOffset
Here are examples for the same.
* Using zone name of India timezone i.e. Asia/Kolkata
ZoneId indianTimeZone = ZoneId.of("Asia/Kolkata");
ZonedDateTime newYearInIndia = ZonedDateTime.of(2019, 1, 1, 0, 0, 0, 0, indianTimeZone);
* Using UTC time offset of California, USA which is UTC-8
ZoneOffset californiaTimeZone = ZoneOffset.of("-08:00");
OffsetDateTime newYearInCalifornia = OffsetDateTime.of(2019, 1, 1, 0, 0, 0, 0, californiaTimeZone);
Why is this better than pre Java 8 classes from java.util?
- Date is a representation of instant in time in milliseconds.
- It also allows interpretation in terms of year, month, day, hour, minute, and second values.
- Calendar provides a way to manipulate date & time in human readable notation.
- GregorianCalendar is a concrete implementation of Calendar providing standard calendar implementation.
- As name suggests, this represents time zone.
Now lets try to represent few from above example using these pre Java 8 classes.
|What to represent?||Example||Pre Java 8 Representation.|
|Only Year||Next leap year||
|Only Year, Month & Day||Birthday ex: 10 January 1981||
Tom's birthday is on Sat Jan 10 00:00:00 PST 1981
|Only Hour, Minute & Seconds||Store opening time like 09:00:00 AM||Didn’t have anything to specifically represent only time.|
|Machine time or particular instance in time||ECG/EKG graph of heart||We can use “new Date()” which stores milliseconds. But still date is a representation of Human time. But closer to what we want here.
As you can see, with pre Java 8 classes, we could represent our examples but not as logical & appropriate as java 8 date-time classes. All of these still had unwanted information which was not necessary in the context of examples.
So legacy date-time API classes did the job but not as well as new java.time package API
Migrating to Java 8 date-time API (java.time package)
Even though Date, Calendar & GregorianCalendar classes are not deprecated, they are officially called legacy by Oracle documentation. Also the new date-time API is better representation as explained above, so you might consider migrating to new Java 8 date-time API.
Migrating to java.time from java.util is not going to be one-to-one. We can’t just replace java.util.Date with java.time.LocalDate or java.time.LocalDateTime as it might not be logically accurate.
First step while migrating to new java.time will be to identify what your Date, Calendar or GregorianCalendar represent functionally? It might represent just “day, month, year” or it might represent “day, month, year with time” or “day, month, year with time & timezone” etc. Once you figure out what exactly you want to represent, then refer to table in earlier section of representation like real-world examples & timezone examples. Choose appropriate classes to represent & use it.