FWIW, I have actually written a scala time library very much along the lines of what Rich is proposing (unfortunately closed source as of this moment). So I'll be so bold as to offer my 2 cents.
Writing a date-time library is not nearly so difficult as many people make it out to be, *
provided* (big caveat) one is willing to make some simplifying assumptions. For instance, my library only supports the Gregorian calendar for times in the range of (roughly) 1677-09-21 until 2262-04-11, and it only supports certain well-behaved time zones (most of the ones anyone really cares about). All told, it is about 1200 lines of scala code, nearly half of which are devoted to parsing and formatting. It does 99.9% of what I want a time library to do (and probably 95% of what 90% of people would want a time library to do).
The joda-time library is extremely general and is capable of handling numerous calendar systems in every conceivable time zone. It pays for this generality in complexity, performance, and usability. That said, even the mighty joda-time library makes simplifying assumptions. For example, even it does not account for leap seconds (
http://joda-time.sourceforge.net/faq.html#leapseconds). If you ask try to ask joda-time for the number of seconds between the epoch (1970-01-01T00:00:00Z) and 2013-01-01T00:00:00Z it will incorrectly tell you that there were 1356998400 seconds. It actualality there where 1356998425 seconds.
So why did I choose to write my own time library rather than just using (or wrapping joda-time)? A number of reasons:
1. joda-time only supports millisecond resolution; I needed a library with nanosecond resolution
2. joda-time is extremely verbose and cumbersome; I wanted a compact, easy-to-use scala DSL
3. certain operations in joda-time are very, very, sloooow; I needed a high-performance library
4. joda-time is too general for my purposes, it makes everything possible, but easy things are too difficult
That said, everyone's requirements differ, and for most people I think a scala wrapper of joda-time would be more than sufficient.
For anyone interested, my library consists of five basic types: Time, Duration, Date, TimeOfDay, and TimeZone. Time, Duration, and TimeOfDay are all value-classes wrapping a Long or Int. Time is a time-zone agnostic representation of an instant in time (represented as the number of nanoseconds since the epoch). Duration is simply a Long representing a fixed number of nanoseconds. Date is semantically a year-month-day triple and TimeOfDay is a cyclic long with a period of 86400 * 10^9 nanoseconds.
One advantage of writing a time library in scala, besides having a nice compact DSL, is the ability to write functions that take an implicit TimeZone whenever necessary. For instance, my Time class (which itself is time-zone agnostic) has functions like:
def date(implicit tz: TimeZone): Date
def tod(implicit tz: TimeZone): TimeOfDay
def midnight(implicit tz: TimeZone): Time
and my Date class has a function
def at(tod: TimeOfDay)(implicit tz: TimeZone): Time
The hardest part about writing this library (apart from the parsing and formatting code) was getting the Daylight Savings Time (DST) transitions correct. DST transitions are extremely complex (being subject to the whims of local government), but, for the most part, this complexity is handled by the standard tz database, which is freely available and easy to use. Even joda-time uses this database to handle DST transitions.
Yes, there are some decisions to make about how to handle DST transitions, but these are not really all that difficult. By way of example, let me answers Alec's question about the meaning of
now + 1.day. In my library, 1.day is a fixed duration which is always 24 hours. So now + 1.day is the same as now + 24.hours. Because of DST transitions it is not always true that now.tod == (now + 1.day).tod. If you wanted the next day at the same time of day you could write instead
(now.date + 1).at(now.tod)with some implicit TimeZone in scope. But of course the difference between those two times may not be exactly 24 hours.
Okay, that was more like 20 cents. Sorry for the long post.
Cheers, Jeff