[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

DateTime getting wrong time zone

Mark J. Reed

10/13/2003 1:50:00 PM

I seem to have found a bug in the DateTime class's determination
of the local time zone. This one-liner demonstrates the problem:

$ ruby -rdate -e 'puts Time.now, DateTime.now'
Mon Oct 13 09:18:14 EDT 2003
2003-10-13T09:18:14-0501

The two classes agree on the local time, but not on the time zone;
EDT (United States' Eastern Daylight Time) is 4 hours earlier than
UTC (-0400); if you ignore daylight savings, we're 5 hours earlier than
UTC (-0500). So where is that extra minute coming from? It's almost as if
the logic were trying to adjust for daylight savings time, but doing so in
the wrong direction and in units of minutes instead of hours.

The only way I have so far discovered to get UTC out of a DateTime is via
DateTime#ajd, which returns the the Astronomical Julian Day number, but that's
enough to verify the one-minute offset. The Julian Day of the
UNIX epoch (1970 Jan 1 00:00:00 UTC) is 2,440,587.5, so I can get the
Julian Day for any given UNIX time_t value (such as the one returned
by Time#to_i) by simply dividing by the number of seconds in a day
(86,400) and adding the epochal JD:

irb(main):001:0> require 'date'
irb(main):002:0> t=Time.now, dt=DateTime.now
irb(main):003:0> puts 2_440_587.5 + Rational(t.to_i, 86_400).to_f, dt.ajd.to_f
2452926.0543287
2452926.0550290

Note the difference - 0.0007003 day, which is 60.5 seconds - one minute
plus a half second, which was probably the elapsed time between the
creation of the two objects (although that seems like an awfully long time
for that operation).

Looking at the source for DateTime::now:

def self.now(sg=ITALY)
i = Time.now
a = i.to_a[0..5].reverse
jd = civil_to_jd(*(a[0,3] << sg))
fr = time_to_day_fraction(*(a[3,3])) + i.usec.to_r/86400000000
d = Time.gm(*i.to_a).to_i - i.to_i
d += d / d.abs if d.nonzero?
of = (d / 60).to_r/1440
new0(jd_to_ajd(jd, fr, of), of, sg)
end

The problem seems to be the sixth line:

d += d / d.abs if d.nonzero?

Which automatically increases the timezone offset by one minute, with
no indication as to why. Can someone (Mr. Tadayoshi Funaba, or
William Webber, are you out there?) perhaps shed some light on this
matter?

-Mark