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

Reply via email to