From: Sam Roberts Date: 2004-03-30T06:20:11+09:00 Subject: possible Time & DateTime RCR: reconciling and extending their apis (Maybe this should be 3 emails... there are 3 issues, but I will try one and see if it sparks any discussion.) What's the difference between Time and DateTime? Time is in absolute seconds since some start date (jan 1, 1970). **Also** it inherits the C libraries knowledge of the local timezone, as well as of daylight savings time. It can only be used for date/times in 1970 and later. DateTime is in absolute days since some start date, with the hour/min/sec within that day. **Also** it implements the Julian and Gregorian calendar conversion, and can have arbitrary offsets from UTC specified. It can be used for the last few thousand years (in places where it was used, basically that means Europe), but there is no knowledge of daylight savings time changes. The situation is a little confusing because the diffences in the APIs are reflections of the underlying implementation technique, not of a conceptual difference between a Time and a DateTime: - seconds vs. days as the absolute time measure - implemented in ruby or uses the C library I have 3 suggestions/requests, described in more detail below: 1 - that DateTime support all the methods of Time, so that it can be used anywhere a Time can, with the the magic of DuckTyping, the only difference will be that DateTime has a larger range 2 - that using times (both Time and DateTime) be made easier by adding some methods to one or both classes 3 - that a way of making DateTime aware of daylight savings time be thought up These 3 are all independent suggestions. ** 1 I would like to request that DateTime be "duck type" compatible with Time, so a DateTime can be dropped into any ruby API that accepts a Time. This may not be entirely possible in ruby 1.x, since they share some method names, but the methods behave differently. Perhaps these can be deprecated, or the docs can mark them as non-compatible, and methods that do the same thing with the same name can be added? The following methods are missing in DateTime, but I think would be trivial to implement: Instance methods -- aTime.methods - aDateTime.methods => [ "dst?" "getgm" "getlocal" "getutc" "gmt?" "gmt_offset" "gmtime" "gmtoff" "isdst" "localtime" "to_f" "to_i" "tv_sec" "tv_usec" "usec" "utc" "utc?" "utc_offset" ] Class methods -- Time.methods - DateTime.methods => "local" "times" --> DEPRECATED "mktime" "at" "utc" "gm" Notes: dst?/isdst is one exception to the "its easy to do" statement. DateTime only knows the offset, it can't know if it is DST, so perhaps it should always return false? #zone() Time -> some local nickname for the timezone ("EST"), useful only within a country DateTime -> an RFC822 style string ("+0530") of the hour and minute offset from UTC #to_s() Time -> "Mon Mar 29 13:19:05 EST 2004" DateTime -> "2004-03-29T13:18:58-0500" +/- Time -> add/sub a second DateTime -> add/sub a day succ Time -> add a second DateTime -> add a day #parse() DateParse#parse(), Time#parse(), and DateTime#parse() all appear to do basically the same thing, with some API differences. The heuristics aren't documented, so its hard to know if there is a more fundamental difference. Time -> uses DateParse.parse, but adds some logic to do 2 digit year to 4 digit conversion, and accepts a Time to use to fill in any defaults DateTime -> implements its own heuristics, are they better or different than DateParse? ** 2 * date/time arithmetic It's hard to do things like add a week, or add a day, to a Time, or even a DateTime. I think the Time and DateTime construction methods should allow objects like this to be constructed more flexibly. They already wrap out-of-range values to the next valid value, in some cases, but not all: [ensemble] ~/p/ruby/vcard $ ruby -r date -e "p (Date.civil(2004, 1, 31) >> 1).to_s" "2004-02-29" [ensemble] ~/p/ruby/vcard $ ruby -r date -e "p (Date.civil(2004, 2, 31) >> 1).to_s" /usr/local/lib/ruby/1.8/date.rb:591:in `civil': invalid date (ArgumentError) There should be ways to add years, months, days, hour min sec to both Time and DateTime, and support for these 6 are partial in both Time and DateTime. * using Time and DateTime together Things to add that would help using DateTime and Time together: Date#to_time - raises ArgumentError if not representable, or should it return a negative number? Time#to_datetime - maybe only defined if you require 'date'? Time#to_date - useful? eql?, <=> - should allow comparisons between Time and DateTime * mutating methods should have a bang Operations that modify a Time or a DateTime could have a bang: Time#gmtime Time#utc Time#localtime * DateTime has more manipulations in its API than Time A number of methods of DateTime aren't in Time, perhaps they can be added? Many of the methods are useful, but you have to convert your Time to a DateTime to use them. Maybe Time is supposed to be "lighter weight" than DateTime? That would be OK, the docs could say that Time is a light-weight date/time representation, with only the range of the system time, and that for a more powerful representation, and many useful utility functions, require 'date', and convert your aTime object to a DateTime using Time#to_datetime(). But, minus the lightweight argument, there is no reason they can't both support exactly the same methods, both object and class! ** 3 Daylight savings time is painful to deal with, but it is important! Not all mornings in Ontario have a 2:30 AM, sometimes there are 25 hours between 10AM one day and 10AM the next! Even if its messy, its true. This isn't such an issue with static DateTime objects, but when you start to do arithmetic with them, to add days and months, you quickly run into the DST problem. It would be really powerful if you could tell DateTime what timezone it is in, not just the current offset, but the rule for how the offset changes (if it does) with DST. Currently, ruby is as weak (or weaker) than ANSI C in dealing with multiple timezones, that are NOT your own local timezone, simultaneously in a single application. This is probably a just a dream... but here's my request: I'd like to see it possible for a DateTime could have it's timezone set, where the timezone consists of: std -> standard offset from UTC dst -> optional, DST offset from UTC, and some way of specifying the changeover This information could be in some kind of raw format, or could even be a string timezone name. In that case, perhaps DateTime could have a class variable that mapped strings to the std/dst definition. Here's a reference to a textual notation that seems good enough to specify most STD/DST time zone transitions, perhaps an equivalent programmatic representation would be enough: http://www.qnx.com/developers/docs/qnx_6.1_docs/neutrino/lib_ref/global.html#TheTZEnvironmentVariable I don't know if this is widely used, or is just a QNX extension. I know OS X (from BSD?) has a zone info compiler, where you can compile textual definitions of timezones into a binary format. Thanks, Sam