On 15-04-08, Alexander Belopolsky wrote:
> On Wed, Apr 8, 2015 at 6:52 PM, Isaac Schwabacher <ischwabacher(a)wisc.edu <ischwabacher(a)wisc.edu>> wrote:
> > > So "storing the offset" and "storing a flag" are not two alternative solutions to the same problem- these
> > > are two solutions to two different problems.
> > I'm viewing a time zone as a map from UTC to local time; for example, America/Chicago is a time zone. I'm not proposing storing the offset as an alternative to storing the *time zone*, I'm proposing it as an alternative to storing whether a given time is DST or not.
> When you are proposing to store something, you also need to specify where you are proposing to store it. In the current design, local time information is stored in the datetime object and the rules that govern UTC to local mapping (and back) are stored in the tzinfo object. The implementors of concrete tzinfo subclasses are supposed to have access to time zone rules and implement utcoffset(dt), together with dst(dt) and tzname(dt) methods.
> Storing isdst in the datetime object would allow utcoffset(dt) to distinguish between 1:30AM before clock change and 1:30AM after. Where do you propose to store the offset?
I propose to add an offset field to datetime.datetime. It should be set precisely when the tz field is set, and it should contain either a timedelta or an integer number of (possibly fractional) seconds, depending on what color the bikeshed gets painted. This is, IIUC, precisely where Lennart is proposing to store the is_dst flag.
I just looked through the datetime documentation, and it looks like the currently blessed way of creating an aware datetime from a naive local datetime and a tzinfo is datetime.replace, which is too low level to handle the job. This method will either need to grow some validation, or there will need to be a tzinfo.localize(localtime, is_dst) method as well.
> If you store it in dt, why would you need the tzinfo?
You can't do arithmetic without a time zone. Which is to say, if you try to do arithmetic without a time zone, you're implicitly doing it in a fixed offset time zone. So there's no way to disambiguate between
"2013-11-03 01:30:00-0500 America/Chicago" + "1 hour" = "2013-11-03 01:30:00-0600 America/Chicago" and
"2013-11-03 01:30:00-0500 America/New_York" + "1 hour" = "2013-11-03 02:30:00-0500 America/New_York".
> > We really don't care whether a time is DST or not;
> You may not care about it, but current tzinfo interface and tzinfo.fromutc(dt) method do. Whatever new features are added to the standard library, they cannot break existing uses. This means that whatever concrete tzinfo implementations we add to stdlib, they must provide an implementation of tzinfo.dst(dt) method.
I don't really mean we don't care; I mean that it's not close to orthogonal to the other things we care about in the way that local time and UTC time are. You'll never ask for *just* the DST flag. So making you look up in zoneinfo whether a given (localtime, offset, tzinfo) triple represents DST or STD is not as onerous, because if you used the other representation, you'd still be looking in zoneinfo for some other piece of information that the user asked for at the same time. So we implement the datetime.astimezone()
> > So our times would look like "2013-11-03 01:30:00-0500 America/Chicago" and an hour later, "2013-11-03 01:30:00-0600 America/Chicago". And all of that information is stored in the datetime object.
> I don't think this is what most people would expect
> $ TZ=America/Chicago date
> Wed Apr 8 18:26:01 CDT 2015
> $ TZ=America/Chicago date +"%c %z"
> Wed 08 Apr 2015 06:27:09 PM CDT -0500
> and not have location as a part of their timestamps.
> Regardless, whatever the proposal to add timezones to stdlib will end up being, it must include the ability to implement an equivalent of UNIX date command shown above.
Sorry, I meant that to show off the internal representation, rather than intending it as the literal string representation. But I *do* think that the right representation of a time zone-aware time is (localtime, offset, tzinfo), and the __repr__ should reflect that. Anyone who wants "CDT" instead of "-0500 America/Chicago" is talking to a human instead of a computer and should use strftime.