Re: [Datetime-SIG] Clearing up terminology
.... [Tim]
[explains that strict/timeline arithmetic _is_ currently done when subtracting or comparing two aware datetimes]
[ijs]
But only when the aware datetimes have different time zones!
Oh, fudge - yes. My mistake! I overlooked that in my explanation. And, to be clear, two datetime objects x and y "have the same timezone" in _this_ context means: x.tzinfo is y.tzinfo That is, iff they share a common tzinfo object. In that case they are indeed subtracted (ditto compared) using classic arithmetic Given that classic arithmetic is used whenever it can be partly justified in under 4 pages of dense text, there's simply not a compelling reason to break from the naive-time model in that case. So I take back everything I said about your specific example:
tz = timezone('America/Chicago') datetime(2013, 11, 3, 1, 30, tzinfo=tz, is_dst=True) - datetime(2013, 11, 3, 1, 0, tzinfo=tz, is_dst=False)
Assuming this isn't some tzinfo implementation that, e.g., sometimes magically replaces instances bound to datetimes, then both datetimes share a common tzinfo member, the result won't change. There are other cases that _will_ change, when the tzinfo members are different objects. If you want code similar to this that does give a timeline arithmetic result, you'll need to use whatever spelling of "use timeline arithmetic" is implemented (if any).
It's precisely because of this behavior that pytz has one fixed-offset DstTzInfo object for each offset attained over a time zone's history, so that two datetimes in the same time zone but with different offsets will have different tzinfo members and therefore be converted to UTC before being subtracted.
Both painful and clever. While I don't personally care about timezone transition anomalies (I've never written an app that cared, nor expect I ever will), if I _did_ I think it's bloody obvious that "the right thing" to do in Python's current state is to stick to UTC for every operation apart from conversions for input or output. Classic arithmetic and timeline arithmetic give the same results in UTC (or any other eternally-fixed-offset timezone). Insert "Doctor! Doctor! It hurts when I do this!" "So stop doing it" ;-)
This also means that addition leaves the datetime with the same fixed offset DstTzInfo object, so that calls to .utcoffset() and .dst() return the wrong result until the datetime object is normalized, which can be accomplished either with tz.normalize(dt) or with dt.astimezone(tz) , except that the second way doesn't work if tz is dt.tzinfo (as opposed to one of the other DstTzInfo objects corresponding to tz).
I won't do the "Doctor! Doctor" joke more than once in a single message ;-)
So anyone who is already using pytz is using timedeltas as durations anyway, it's just that they and Stuart Bishop have to jump through hoops to accomplish it. Which, come to think of it, might mean that the backward compatibility problem is overrated-- the behavior could be changed for aware datetimes only, and .normalize() could be added as a no-op.
I believe Stuart also strongly recommends sticking to UTC (at least for people who do care about transitions). I conclude he went to all the trouble primarily because he found it to be an irresistibly bizarre technical puzzle. I'm only surprised that attitude is apparently contagious ;-)
... I'm not clear on how narrowly you mean "this case"
Since I retracted what I said, doesn't matter.
What about
tz = timezone('America/Chicago') dt = datetime(2013, 11, 3, tzinfo=tz) [[(dt.astimezone(timezone.utc) + timedelta(hours=n1)).astimezone(tz) - dt.astimezone(timezone.utc) + timedelta(hours=n2)).astimezone(tz) for n2 in range(5)] for n1 in range(5)]
?
I think the project would be better served if you directed this ingenuity and energy into creating unit tests, or at least a persistent document that grows over time, or a wiki entry ... What do _you_ think should happen? I agree that getting edge cases right is important, but since I strongly doubt I'll be working on them it's of little real use to invite me to think about them. At heart, they're just not interesting to me - and mailing lists are black holes. After I finish answering, this will all be lost in time ;-) Briefly as I can, because nobody yet knows what will and won't be implemented, or when each piece that is implemented will land: - Conversions have always done the best job they could in all cases; conversions are _outside_ the "naive time" model. - But conversions inherit utcoffset()'s limitations. Provided utcoffset's current limitations are repaired, conversion should do the correct thing in all cases. It cannot today. - Since you start in Chicago standard time, I expect that (assuming it's implemented) some spelling.of is_dst will record "no, it's not DST" in your dt object. That will never change across the duration of the program. There is no spelling of is_dst today. - The two instances of `dt.astimezone(timezone.utc)` could be hoisted out of the nested loops and computed just once: it's a loop invariant. That value should already be computed correctly (it's converting a not-near-an-edge-case Chicago daylight time to UTC, right? easy). - And there doesn't appear to be anything tricky about the two additions.. Their left-hand sides are the same loop invariant, and then a varying number of hours are added to that invariant. Finally, the additions are performed _in_ UTC, where classic and timeline arithmetic produce the same results. Nothing changes, and all that should also already be done correctly - You've contrived for the additions to create two UTC time spellings that will convert to the same time spelling in America/Chicago (the "repeated hour" at the end of Chicago DST). Both now and regardless of what may change, both such UTC spellings will convert to 1:00:00 Chicago time, via astimezone(tz). - The top-level subtraction will continue to use classic arithmetic because both operands share the same tzindo object. Unless some spelling of "use timeline arithmetic all the time" is implemented that's somehow triggered by code outside the fragment shown. So I don't expect any change to the _displayed_ results here. _If_ the top-level subtraction were done with timeline arithmetic instead, then I would expect changes, provided an .is_dst equivalent is implemented. In that case, some astimezone(tz) intermediate results would change, not in the Chicago HH:MM:SS results delivered, but that some of the Chicago 01:00:00 results would have is_dst False and others True. Classic arithmetic won't even see that, but timeline subtraction would take those differences into account. Enough? Did I even stumble into the issue you were _really_ wondering about? ;-)
... ...I might have had some comments of that nature in my code until fairly recently. Though they weren't as angry as the comments about getting pytz and dateutil.tz to interoperate.
Hear about the guy who went to the doctor and complained "Doctor! Doctor! It hurts when I do this!"? Na, me neither ;-)
Or the comments about the device that tried to store sub-second resolution data in Excel format (days since 1899-12-30)... to five decimal places.
I _am_ an expert on floating-point trivia. In case you were wondering, the person who wrote the software for that device was ... optimistic ;-)
participants (1)
-
Tim Peters