[<random...@fastmail.com>] > My context is that I am working on an idea to include utc offsets in > datetime objects (or on a similar object in a new module), as an > alternative to something like a "fold" attribute. and since "classic > arithmetic" is apparently so important,
Love it or hate it, it's flatly impossible to change anything about it now, for backward compatibility. > I'm trying to figure out how > "classic arithmetic" _is actually supposed to work_ when adding a > timedelta to a time lands it on the opposite side of a transition (or in > the middle of a "spring forward" gap). datetime arithmetic is defined in the Python docs. > If there is a "fall back" transition tonight, then adding a day to a > time of 12 noon today could end up as: > > 12 noon tomorrow, offset still DST. > 12 noon tomorrow, offset in standard time, 25 hours from now in real > time. > 11 AM tomorrow, offset in standard time, 24 hours from now in real time > > Which one of these is "classic arithmetic"? 12 noon tomorrow in every case, regardless of tzinfo and regardless of whether any kind of transition may or may not have occurred. Whether it is or isn't in DST in this specific case isn't defined by Python - that's entirely up to what the tzinfo implementation says. The _intended_ way of implementing tzinfos would say it was in standard time. > Pytz (if you don't > explicitly call a "normalize" function) results in something that looks > like the first. Yes, because pytz always uses a fixed-offset tzinfo. There is no difference between timeline arithmetic and classic arithmetic in any fixed-offset zone. > In one of the models I've thought of, you can get the > second by replacing the tzinfo again, or the third by doing astimezone, > but the first preserves "exactly 24 hours in the future" in both the UTC > moment and the naive interpretation by leaving the offset alone even if > it is an "unnatural" offset. > > The second one above is what you get when you call normalize. Yes. .normalize() effectively converts to UTC and back again In fact, this is all it does: def normalize(self, dt, is_dst=False): if dt.tzinfo is self: return dt if dt.tzinfo is None: raise ValueError('Naive time - no tzinfo set') return dt.astimezone(self) .fromutc() is called as the last step of .astimezone(), and .pytz overrides the default .fromutc() to plug "the appropriate" fixed-offset pytz tzinfo into the result. > My question was whether there are any real implementations that work the > intended way. dateutil, plus all implementations anyone may have written for themselves based on the Python doc examples. When datetime was originally released, there were no concrete tzinfo implementations in the world, so lots of people wrote their own for the zones they needed by copy/paste/edit of the doc examples. > If there are not, maybe the intended semantics should go > by the wayside and be replaced by what pytz does. Changing anything about default arithmetic behavior is not a possibility. This has been beaten to death multiple times on this mailing list already, and I'm not volunteering for another round of it ;-) -- https://mail.python.org/mailman/listinfo/python-list