5 Reasons Why Java’s old Date and Calendar API was a Bad Design
1. It’s not intuitive
Look at the following example, where a user simply wants to create a Date object for 25th December 2017, 8.30 at night, do you think this is the right way to represent that date in Java?
Date date = new Date(2017, 12, 25, 20, 30);
Well, even though it is looking alright, it is not correct. The above code contains two bugs, which is not at all intuitive. If you are using the java.util.Date class, then you must know that year starts from 1900 and month starts from zero i.e. January is the zeroth month, not the first.
Here is the right way to declare same date in Java:
int year = 2017 - 1900;
int month = 12 - 1;
Date date = new Date(year, month, 25, 20, 30);
You must remember that January is 0, December is 11, and Date use years from 1900.
Btw, If you are new to the Java world then I also recommend you go through The Complete Java MasterClass on Udemy to learn Java in a better and more structured way. This is one of the best and up-to-date courses to learn Java online.
2. Timezones
Prior to JDK 8, Java uses String to represent TimeZone, a very bad idea. Ideally, they should have defined a constant or Enum instead of allowing the user to pass String.
Since String lacks compiler checks, it opens a door for spelling mistakes and silly human errors. Java’s naming convention with timezones also doesn’t help.
TimeZone zone = TimeZone.getInstance("America/NewYork");
Unfortunately, it’s not correct. It contains a silly but hard-to-find mistake, the time zone string is wrong here. The correct timezone String is “America/New_York” as shown in the following example
TimeZone zone = TimeZone.getInstance("America/New_York");
Had they have used Enum, these would have been flagged by the compiler or your IDE as soon as you typed. Another example of this kind of gotcha is “Asia/Hong_Kong”, so be careful while using those timezones in Java.
3. Calendars are Tricky and Errorprone
The Calendar class is also not very user-friendly or intuitive in Java. You just cannot apply common sense or predictive knowledge. For example in the following code, we are trying to create a Calendar object for a date in a particular timezone, It will not show any compile-time error but it will not work as you expect.
Calendar cal = new GregorianCalendar(date, zone);
The right way of using Calendar object with date and timezone is as following :
Calendar cal = new GregorianCalendar(zone)
cal.setTime(date)
So, if you haven’t used Calendar API for a long time, there is no chance you can get it right after that.
Here is another example of how intuitive the new Date and Time API has as compared to the old Date and Calendar API:
If you are interested in more examples of old and new Date and Time API like this, I suggest exploring a good Java 8 book like Java SE 8 for Impatient by Cay S. Horstmann. One of my favorite author, who explains the details which matter most.
4. Formatting Dates is Hard
Formatting dates are one of the most common tasks while using Dates in Java. Given multi-threading is the core strength of Java, one should expect that their core classes like String, Integer, or Date should work seamlessly in concurrent applications.
Java designers made a good job with String and Integer but did a really poor job with Date, formatting date was very tricky in Java.
DateFormat fm = new SimpleDateFormat("HH:mm Z");
String str = fm.format(cal);
This example contains a couple of bugs, first, you have to set Timezone for DateFormat class and second, you cannot pass a Calendar object to format method, you can only pass a java.util.Date object, hence you need to first convert Calendar to Date in Java and then pass it to the format() method as shown below:
Here is the right way of using the Calendar class with SimpleDateFormat in Java.
DateFormat fm = new SimpleDateFormat("HH:mm Z");
fm.setTimeZone(zone);
Date calDate = cal.getTime();
String str = fm.format(calDate);
You must remember that Calendar cannot be formatted in Java and DateFormat class is not thread-safe so it cannot be used in multi-threaded Java applications without proper synchronization.
5. Mutable
This is IMHO biggest mistake Java designers have made in the JDK. Unlike String or Integer, Date is mutable. It’s possible for you to pass a client to get the reference of Date and change it without the owner of that Date class knowing, as shown in the below example
Person p = new Person()
Date birthDay = p.getBirthDay()
birthDay.setTime();
Now that person will have a different birth date, so bad. That’s why whenever you have to return a Date from your class, you must return a new Date object or clone, you should never return the original Date object, it breaks the Encapsulation of the class.
If these reasons were not enough, the SQL Date/Time/Timestamp also extends the java.util.Date class and violates the Liskov Substitution Principle.
That’s all on why Java’s Date, Calendar, and Time classes suck before Java 8. It’s important to learn from experience and that’s what Java designers have done that. For you, a Java developer is also important to know the shortcomings of Java’s old Date and Calendar API to appreciate and acclaim the greatness of Java 8’s new Date and Time API.
If you want to learn new features of Java 8 and the new Date and Time API, I suggest joining these Java 8 courses or reading Java SE 8 for Impatient by Cay S. Horstmann, one of the best books to learn Java 8 quickly.