As an experienced java developer, I have worked on many time sensitive applications. These include scheduling systems, power meter reading systems and various account management systems, and have spent numerous hours dealing with bugs introduced by Daylight Saving Time transitions and other Timezone related problems. I am also old enough to remember the whole Y2K fiasco. These issues all stem from the same ill-fated attempt to convey more information than time in a time or date field. Time reporting always requires a TimeZone and this requires a Locale and the time to determine. This may seem somewhat circular but thanks to Ben Franklin’s great idea (Daylight Saving Time), you do need to know what time it is to tell you what TimeZone you are in. These issues can all be avoided by following a simple rule of thumb in all time management processes.
Always use Long or long (a 64 bit number) to store, pass and process dates times or intervals, only convert to Date, Calendar or DateTime objects when interacting with people.
This Long or primitive long time (or date if you will) represents the difference, measured in milliseconds, between the time reported and midnight, January 1, 1970 UTC. This is a well-known and agreed upon reference for almost every computer system or language known to man. It is also conveniently found in Java by calling
or with C# (to be fair here)
All of the languages mentioned above also provide simple ways to convert long millisecond values to Date or DateTime objects.
If one keeps foremost in your mind that Dates and the like are human artifacts and should only be used when interacting with humans, using long (or Long) to store times and dates is a natural conclusion. In a multi-tier application, it is generally the browser or App container that actually presents the time and date information to the end user and they can adjust the long values to Dates and Times while taking into account any bizarre Daylight Saving Time rules of the geographic time zone in which the user might find themselves. With distributed applications and smart clients, it is presumptuous and ridiculous for any server based application to tell the user “what time it is”, or decide how to display dates and times for the user.
Using long or Long values as Date proxies has another advantage, JSON or XML serialization produces smaller data streams. Converting a Date to JSON yields something this: “2013-08-08T01:35:05.793Z” , whereas a long time in JSON renders as “1376055673793”, yielding a JSON savings ratio of about 50%. These two things convey exactly the same information, once the context of the long is understood by sender and receiver, and by saving 50% of the stream you can improve system performance.
The end of time is a convenient concept in interval calculation. It is needed to indicate a never ending interval. Sometimes it is represented by a null Date, sometimes it is represented by 12-31-9999, sometimes it is even represented by “99-99-9999”, only if the application uses the anti-pattern of storing Dates as Strings. I would argue these approaches are all basically flawed. Null should only be used to convey the absence of data and it is difficult to ascertain if a given time falls between the start time and Null. Using 12-31-9999 assumes a Timezone and would not be same date for a user in New Zealand. I’ll go out on a limb here and say that using “99-99-9999” to indicate the end of time is just plain stupid. When using Long values for time processing the end of time is easily determined as Long.MAX_VALUE (9223372036854775807L), when converted to Date on my computer using (new Date(Long.MAX_VALUE)) it becomes Sun Aug 17 01:12:55 CST 292278994. This is long after any previous end of times mentioned and can be compared with equality to an End of Time generated on a different computer in a different country. For the beginning of time one could use new Date(0l) unless one is interested in pre-computer history (like birth dates etc). With these convenient min and max values interval processing is greatly simplified and is TimeZone independent.
The database should also not need Date fields. The only time Date fields should exist in a database is if end users query the database directly using SQL or direct query tools. This eliminates the need to consider the TimeZone of the database in your date calculations, and also prevents you from converting the same data when you read it from the database. Using my proposal will make date/time fields like synthetic keys, in that they are “never seen by people” but essential to the structure of the data.
In summary Date and Time objects should only be needed in the User Interface, not in the database, not in the domain layer and not in an API. That is my key message and by following that simple rule your Daylight Savings time issues will melt away and your application performance will improve.