java.util.Date is slowly but surely deprecated into the Sun-set, with
java.time taking up its mantle, it’s worth pausing to learn some lessons from its troubled life before letting it rest in peace.
The most obvious lesson is that date–time handling is harder than people expect — even when they’re expecting it. It is a truth universally acknowledged that a single programmer in possession of the belief they understand dates and times, must be in want of a code review. But that’s not what I want to focus on here, nor is it the importance of immutability for value types, what makes a class (un)suitable for subclassing, or how to use classes rather than integers to express a rich domain.
Source code is made up of spacing, punctuation, and names. All these convey meaning to the reader, but names are where most meaning is carried (or dropped). Names matter. A lot.
Given its name, it would be nice if a
Date represented a calendar date, i.e., a specific day… but it doesn’t. It represents a point in time that can be viewed as having a date component. This is more commonly referred to as a date–time or, if you want to put it into code, a
Time also works, as it is the overarching concept. Sometimes finding the right name is hard; in this case it’s not.
Now we understand what we mean by date, date–time, and
Date, what does
getDate do? Does it return the whole date–time value? Or perhaps just the date component? Neither: it returns the day of the month. In programming circles this value is more commonly and specifically referred to as day of month, not date, a term normally reserved for representing a calendar date.
And while we’re here, yes,
getDay would have been better named
getDayOfWeek. Not only is it important to choose a name that is correct, it is important to recognise and resolve ambiguous terms, such as day (of week, of month, of year…?). Note that it is better to resolve naming issues by choosing a better name rather than by javadoc.
Names are tied to conventions and conventions are tied to names. When it comes to conventions, prefer one (not many), prefer to express it clearly, and prefer one that is widely recognised and easy to use rather than one that is niche and error prone (yeah, C, I’m looking at you).
For example, Apollo 11 landed on the Moon at 20:17 on the 20th day of July (the seventh month) in 1969 (CE, UTC, etc.). But if you call
getYear expecting these numbers, expect disappointment:
getTime returns a negative number of milliseconds from the start of 1970;
getDate returns 20 (as expected, it counts from 1);
getMonth returns 6 (months count from 0); and
getYear returns 67 (years count from 1900, not 0 and not 1970).
Good naming is part of design. It sets expectations and communicates a model, showing how something should be understood and used. If you mean to tell the reader
getMillisSince1970, don’t say
getTime. Specific names inspire you to consider alternatives, to question whether you’re capturing the right abstraction in the right way. It’s not just labeling and it’s not just
java.util.Date: This is about the code you write and the code you use.