It's become beyond obvious that I'll never be able to make enough time to respond to all of these, so I'll address just this for now. because it's impossible to make progress on anything unless there's agreement on what technical terms mean:
[Carl Meyer <[email protected]>] >>> If you are doing any kind of "integer arithmetic on POSIX timestamps", you >>> are _always_ doing timeline arithmetic. [Tim] >> True. [Carl] >>> Classic arithmetic may be many things, but the one thing it definitively is >>> _not_ is "arithmetic on POSIX timestamps." [Tim] >> False. UTC is an eternally-fixed-offset zone. There are no >> transitions to be accounted for in UTC. Classic and timeline >> arithmetic are exactly the same thing in any eternally-fixed-offset >> zone. Because POSIX timestamps _are_ "in UTC", any arithmetic >> performed on one is being done in UTC too. Your illustration next >> goes way beyond anything I could possibly read as doing arithmetic on >> POSIX timestamps: [Carl] > Translation: "I refuse to countenance the possibility of Model A." Not at all. I've tried several times to get it across in English, so this time I'll try code instead: def dt_add(dt, td, timeline=False): ofs = dt.utcoffset() as_utc = dt.replace(tzinfo=timezone.utc) # and the following is identical to converting to # a timestamp, "using POSIX timestamp arithmetic", # then converting back to calendar notation as_utc -= ofs as_utc += td if timeline: return as_utc.astimezone(dt.tzinfo) else: # classic return (as_utc + ofs).replace(tzinfo=dt.tzinfo) That adds an aware datetime to a timedelta, doing either classic or timeline arithmetic depending on the optional flag. If you want to claim this doesn't do either kind of arithmetic correctly, prove it with a specific example (of course cases where it's impossible to do _conversions_ correctly today would be off-point). Here's a variant of an earlier specific example: from datetime import datetime, timedelta, timezone from pytz.reference import Eastern turkey_in = datetime(2004, 10, 30, 15, tzinfo=Eastern) DAY = timedelta(days=1) turkey_out1 = dt_add(turkey_in, DAY, timeline=True) turkey_out2 = dt_add(turkey_in, DAY, timeline=False) print(turkey_in) print(turkey_out1) print(turkey_out2) and its output: 2004-10-30 15:00:00-04:00 # start 2004-10-31 14:00:00-05:00 # "a day later" in timeline 2004-10-31 15:00:00-05:00 # "a day later" in classic "Timeline" arithmetic accounts for that an hour was inserted when DST ended, and "classic" does not. The "POSIX timestamp arithmetic" part is identical across both cases. The only difference is in how the POSIX timestamp - which is always and only a count of seconds in UTC (which isn't my definition - it's POSIX's) - is converted back to local calendar notation at the very end. I believe you have _pictured_ the POSIX timestamp number line annotated with local calendar notations in your head, but those labels have nothing to do with the timestamp arithmetic. The labels have only to do with the functions used to map local calendar notations to and from POSIX timestamps. Those labelings are the difference between "timeline" and "classic" arithmetic at the higher level of aware datetime arithmetic. At the POSIX timestamp level, an integer is just an integer, with no defined meaning of any kind beyond a count of seconds in UTC. and a POSIX-defined mapping to and from propleptic Gregorian calendar notation. That said, two things to note: 1. The "as_utc -= ofs" line is theoretically impure, because it's treating a local time _as if_ it were a UTC time. There's no real way around that. We have to convert from local to UTC _somehow_, and POSIX dodges the issue by providing mktime() to do that "by magic". Here we're _inside_ the sausage factory, doing it ourselves. Some rat guts are visible at this level. If you look inside a C mktime() implementation, you'll find rat guts all over that too. But it's no problem for Guido ;-) We just set the hands on a UTC clock to match the local clock, then move the hands on the UTC clock by the amount the local clock is "ahead of" or "behind" UTC. In that way you can indeed picture the operation as being entirely "in UTC". 2. This would be a foolish _implementation_ of classic arithmetic, but not for semantic reasons. It's just grossly inefficient. Stare at the code, and in the classic case it subtracts the UTC offset at first only to add the same offset back later. Those cancel out, so there's no _semantic_ need to do either.. It's only excessive concern for theoretical purity that could stop one from spelling it as return dt + td from the start. That's technically absurd, since it's doing POSIX timestamp arithmetic on a timestamp that's _not_ a UTC seconds count. Its only virtue is that it gets the same answer far faster ;-) BTW, the same kind of reasoning shows why the value of the `timeline=` flag makes no difference in any case a fixed-offset zone is being used. Which is, concretely, what I mean by saying that timeline and classic arithmetic are exactly the same thing in any fixed-offset zone. _______________________________________________ Datetime-SIG mailing list [email protected] https://mail.python.org/mailman/listinfo/datetime-sig The PSF Code of Conduct applies to this mailing list: https://www.python.org/psf/codeofconduct/
