I can only echo the perceptive words of Vedha Pitkar, who indicates that it is a challenging and indeed vexing area. It is not only Java - this area is challenging in all programming languages. It turns out that there are enough things about dates and times that are non-obvious or even counter-intuitive, that it presents some real challenges both for implementors and for application programmers.
The first Java date/time implementation was coded in something of a rush by James Gosling, and he got all caught up in the minutiae of leap seconds and royal observatories. He followed prevailing practice of the early 90's and TRIED TO SAVE SPACE BY NOT USING THE FULL FOUR DIGIT YEAR!! Arghhh! In the Date package, years are stored as (year-1900), so 1999 would be 99 (which kinda seems OK), but 2004 is 104 (which really is NOT ok). You can see all this in the comments if you read the source code. Just java tells you where to find the source and how to unpack it, and how to look at it - see page 62. There are a LOT of other problems with Date too, but lets not get into that now.
People pretty soon realized this date stuff was the most tremendous screw-up, but then Sun was caught in the bind of backwards compatibility. Unlike Microsoft, which has the "API of the Month Club" and jerks around its development community like crazy (right now MS is trying to push everyone onto the .Net bandwagon, with noticeable lack of success. Programmers are asking, quite rightly "why should I learn all that .net stuff when you are going to yank it all around again with Longhorn (next release of Windows)?").
Anyway, Sun doesn't do that - Sun has made huge efforts to keep Java backwards compatible, and only a little while ago one of the compiler development team engineers was telling me about an old Java binary he had laying around. He looked at the date on it, and it was from 1995! Before even the FCS of Java! He tried running it, and to his surprise (with all the changes in the JVM, the class file format, the libraries and so on) it Just Ran Perfectly!
So for reasons of backward compatibility, and keeping existing code running, Sun did not rip out and throw away Date. Instead most of the class was deprecated, and some new classes Calendar and friends were adopted. I have got 5 pages on Calendar utilities starting at page 483 in Just Java.
The Calendar classes were written by IBM, but not for Java. They were original developed for the ill-fated Pink project from the Taligent joint venture between Apple and IBM. In one of the great "Might Have Beens" of history, Apple and IBM had got together in the early 90's to develop an OS environment/language that was positioned squarely where Java is. They should have got there first! They didn't! Sun did, and the results are what we know and love today.
So IBM had tons of date processing code in nominally better shape than Sun's Date class, so they did a quick re-write into Java , presto-chango! Date problems all fixed!? Not really. IBM's new code sucked almost as badly as the original Date class. The problem was and is that Calendar is over-generalized. That allows you to set up a e.g. Nepalese calendar, but adds tremendous complexity to the case that 99% of programmers have to use, the Gregorian calendar.
Well, I could yammer on for a long while about the errors of over-generalization, but I will probably overstay my welcome and I don't want to do that. Let me just say that I do not mean to denigrate anyone's work, just point out that programming is a very human endeavor, and therefore subject to all the weaknesses, defects and frailities of the human condition. Having taken 2 whacks at it now, and having a MUCH larger code base using Calendar at this point we are stuck with what we have, and just have to make the best of it.
Best practices for date? Follow these three rules: 1. Keep the code as simple as possible, and do not over-generalize. 2. Comment carefully to say what your design is, and what you intend 3. Translate all date-times into a fixed calendar and GMT directly on input. Keep all date-times in that internal format at all times Process all date-times in that internal format at all times. When you are about to output a date/time for display, make the appropriate conversion to local calendar/timezone at that specific point.
Author of <a href="http://www.amazon.com/exec/obidos/ASIN/0131482114/ref=jranch-20" target="_blank" rel="nofollow">Just Java(TM) 2 (6th Edition)</a>
Thanks for the highly entertaining history of date classes and such. I'm working on a time/date-stamp algorithm in C for an embedded system and I can tell you it's a pain in the lower-regions, but not as bad as Java's Date class.
Give a man a fish, he'll eat for one day. Teach a man to fish, he'll drink all your beer.
Cheers, Jeff (SCJP 1.4, SCJD in progress, if you can call that progress...)
That was interesting history on java dates. Thanks for the tips.
One more question -
From Javadocs for Timestamp -
Due to the differences between the Timestamp class and the java.util.Date class mentioned above, it is recommended that code not view Timestamp values generically as an instance of java.util.Date. The inheritance relationship between Timestamp and java.util.Date really denotes implementation inheritance, and not type inheritance.
Would it be safe to ignore that warning, if I am only interested in the date, hours and minutes part of the Timestamp? i.e. If I am not concerned with microsecond precision, Can I write my 'Date' utility classes using java.util.Date, and safely pass java.sql.Date, Time or Timestamp objects?
Peter van der Linden
Joined: Sep 28, 2004
> Would it be safe to ignore that warning, if I am only interested in the > date, hours and minutes part of the Timestamp?
Good work on getting a second opinion on this subtle area! And Especially Good Work on reading the API, and finding a note of caution there, and asking about the practical impact of that! That kind of attention to detail is exactly the sort of skill that really good programmers show!
If I were in your position, I think I would heed the warning and NOT use the superclass of Date to represent java.sql.Date, java.sql.Timestamp and java.sql.Time. One of the things you are sure to be doing is comparing for equality, and the API docs explain how that is lacking. [This seems like a really badly put together part of the API, but we knew that already].