From: Sam Roberts Date: 2004-03-21T05:54:55+09:00 Subject: Re: bug in Time, it wraps some dates to next month Quoteing hal9000@hypermetrics.com, on Sun, Mar 21, 2004 at 05:20:09AM +0900: > Sam Roberts wrote: > >Possibly you are thining of Date.new(), which allow negative months, and > >negative daysofmonths, like the C mktime()? However, it doesn't allow > >out of range values: > > > >[ensemble] ~/p/ruby/vcard $ ruby -rdate -e "p Date.new(2004, 2, 29).to_s" > >"2004-02-29" > >[ensemble] ~/p/ruby/vcard $ ruby -rdate -e "p Date.new(2004, 2, 30).to_s" > >/usr/lib/ruby/1.6/date.rb:147:in `new3': invalid date (ArgumentError) > > from -e:1 > > Personally I think I'd like to reduce our dependence on the C lib. In terms of freedom from idiosyncracies of the systems C library implementation, I absolutely agree. > I think I'd like to see an exception or at least a nil return value > for (e.g.) Feb 29, 2005 or November 31 of any year. I could live with that, though what would be more useful is for this to work: [ensemble] ~/p/ruby/vcard $ irb irb(main):002:0> now = Time.now.to_a [44, 30, 15, 20, 3, 2004, 6, 80, false, "EST"] irb(main):003:0> now[3] += 40 60 irb(main):004:0> now [44, 30, 15, 60, 3, 2004, 6, 80, false, "EST"] irb(main):005:0> later = Time.mktime(*now) ArgumentError: argument out of range from (irb):5:in `mktime' from (irb):5 I would like to see this give me 3:15PM on the day 40 days from the current day. Right now, a naive implementation would be to take Time.now, and add 40 times the number of seconds in a day. But, if you went past a DST change, that wouldn't give you 3:15PM! Instead, I do this: class Time # Addition of a single day, respecting the local timezone. # Does this do as I expect over DST? What if the hour doesn't # exist # in the next day, due to DST changes? def plus_day(days) d = Date.new(year, month, day) d += days Time.local(d.year, d.month, d.day, hour, min, sec, usec) end end Because Date knows how to have days added to it, and to wrap past the end of a month. Anybody have a better suggestion? Perhaps I'm missing something, or maybe 1.8 has a better way? It's quite difficult to correctly do date manipulations in the face of timezones and DST, and ruby has some powerful date libraries, but they are very low-level, doing things like adding and subtracting units of months/days/weeks from a Time is not easy. I've some methods to propose as standard, or just on the wiki, for doing this kind of thing. Maybe tomorrow they will be finished. > I wonder if this would break any existing code? Probably something Wouldn't be the only thing in 1.8 to break existing code! Cheers, Sam