Zefram schreef: > There are two fundamental problems with DateTime's handling of leap > seconds: one pertaining to the future, and one pertaining to the past.
For every future leap second, there will be a version of DT that handles it correctly. That the current implementation can not, is only an implentation problem :-). Seriously, for problems like "2030-06-30T23:59:59Z + 1 second = ????", you need to make an assumption about future leap seconds. There either will or will not be a leap second at that point, and there is no way we can predict it. DT has chosen the option to ignore unannounced leap seconds; the only reasonable alternative I can see is to refuse to do this kind of date math at all for dates later than 2006-12-31. That is a decision that may not be appreciated by the users of our modules that are not as familiar with leap seconds as you. For past times: yes, you are right; this is a design decision. the 'rubber seconds' aren't that much a problem; we just use "GMT" seconds before 1972, not SI seconds. The partial leap seconds are a bit harder to rationalize away. We should not perhaps be calling our time scale "utc"; but that would again be hard to explain to ordinary users. > There is no tradition (AFAIK) of calculating the fractional JD the > way you do, with the JD incrementing at a different rate for the whole > leap-second-containing day. The official formulae that use JD (usually > MJD actually) with UTC have it increase always at the standard rate of > 1/86400 per second. That's interesting. I think the current implementation of jd() was just chosen more or less at random, because noone here really realised that there is an official way of handling this. Thanks for bringing it to our attention; it's probably a bug that should be fixed. > In that model it undergoes a discontinuity at the end > of a leap, decrementing by 1/86400 at the end of a positive leap second. At the *end* of a leap second? That seems counterintuitive, but if you say so... This would mean that the jd value of time points during the leap seconds appear to belong to the next day. By the way, it seems that my DT::F::E::JD module gets this right. use DateTime; use DateTime::Format::Epoch::JD; my $dt = DateTime->new( year => 2005, month => 12, day => 31, hour => 23, minute => 59, second => 59, time_zone => 'UTC' ); for (1..4) { printf "%s.%03d %.6f %.6f\n", $dt, $dt->millisecond, $dt->jd, DateTime::Format::Epoch::JD->format_datetime($dt), "\n"; $dt->add( nanoseconds => 5e8 ); } $dt = DateTime->new( year => 2006, month => 1, day => 1, time_zone => 'UTC' ); for (1..3) { printf "%s.%03d %.6f %.6f\n", $dt, $dt->millisecond, $dt->jd, DateTime::Format::Epoch::JD->format_datetime($dt), "\n"; $dt->add( nanoseconds => 5e8 ); } Output: DateTime DT->jd() DT::F::Epoch::JD ======== ======== ================ 2005-12-31T23:59:59.000 2453736.499977 2453736.499988 2005-12-31T23:59:59.500 2453736.499983 2453736.499994 2005-12-31T23:59:60.000 2453736.499988 2453736.500000 2005-12-31T23:59:60.500 2453736.499994 2453736.500006 2006-01-01T00:00:00.000 2453736.500000 2453736.500000 2006-01-01T00:00:00.500 2453736.500006 2453736.500006 2006-01-01T00:00:01.000 2453736.500012 2453736.500012 Eugene