At a former company, a cow-orker of mine had cobbled up a set of date and time classes that he declared “general purpose” and “bug free.” About three months later, and after he had left the company, I had to do an 11th hour re-write of the code, just prior to releasing our company’s first product.
Some of the bugs I found:
- The classes had a pretty interface with lots and lots of range, but internally the code used the Unix epoch of 1970 (so no birthdays before then, for instance). It was round-tripping the 1970 epoch through the standard Unix 1970-based routines as well
- Didn’t handle 400-year cycle of leap years
- Fell apart in 2038, like everything else will (Unix epoch, natch)
- Fell apart in 2008, 2010, 2012, and some other years, as I recall. One failure was like some random day in March 2007, I forget why
- Obviously didn’t handle screw cases like the calendar skipping that happened in 1582
- Forget about supporting astronomy or geology applications…
… and other things.
I recall writing unit tests that stepped through the ranges that we definitely cared about (several tens of thousands of years around the current epoch), and also stepped plus-and-minus in the billions of years ranges (by millions or thousands, I think). Random tests, too.
I also recall spending a lot of time reconciling OLE’s idea of date-and-time. (Don’t ever let me catch you using floats for something like this. Really. I’ll find you).
This stuff is not easy to get right, but everyone thinks that it is. Maybe that’s why people get it wrong so often (“Oh, it’s just same date/time code, I’ll just whip this out and go to lunch. Umm, ’30 days hath November, except September, May, and, uh…'”)
Required reading: Calendrical Calculations. Unless you write stuff used by archeologists can probably ignore the Mayan (etc.) calendars, but they’re fun to read about.