[issue31800] datetime.strptime: Support for parsing offsets with a colon
Paul G added the comment: This seems very useful to me. I very frequently advise people *against* using dateutil.parser (despite my conflict of interest as maintainer of dateutil) for well-known formats, but the problem frequently comes up of, "what should I do when I have date created by isoformat()?", to which there's no clean satisfying answer other than, "use dateutil.parser even though you know the format." I think the strptime page that Mario linked to is evidence that the %z directive is *intended* to match against -HH:MM, and so that might be the most "standard" solution. That said, I somewhat prefer the granularity of the GNU date extensions %z, %:z and %::z, since this allows downstream users to be stricter about what they are willing to accept. I think either approach is defensible, but that *something* should be done soon, preferably for the 3.7 release. -- nosy: +p-ganssle ___ Python tracker <https://bugs.python.org/issue31800> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue31222] datetime.py implementation of .replace inconsistent with C implementation
Paul G added the comment: @r.david.murray In the other thread, you mention that the full test suite is run against the C and Python implementations, so that answers the question of how to write the tests. I think treating it as an enhancement in Python 3.7 makes a reasonable amount of sense - it's clearly under-specified at the moment and people are probably relying on the CPython behavior (dateutil definitely is in the latest stable release, but not on master). Saying "it's implementation-specific before Python 3.7 but in Python 3.7+, the spec says it should use self(type)" is fine by me. It's not particularly hard to work around if you're subclassing datetime anyway. Among the major libraries that provide their own datetime objects: - Arrow seems to use composition (https://github.com/crsmithdev/arrow/blob/master/arrow/arrow.py) - pendulum subclasses, but implements their own "replace": https://github.com/sdispater/pendulum/blob/master/pendulum/pendulum.py#L25 - delorean uses composition: https://github.com/myusuf3/delorean/blob/master/delorean/dates.py#L174 - maya uses composition: https://github.com/kennethreitz/maya/blob/master/maya/core.py#L72 I'd say for the most part it's not a major issue to change it even as a bugfix, particularly if the line we're going with is "it was always implementation-specific", but there's also no rush. -- ___ Python tracker <http://bugs.python.org/issue31222> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue31222] datetime.py implementation of .replace inconsistent with C implementation
New submission from Paul G: In the .py implementation of datetime.replace (and date.replace and time.replace), the new datetime is created using the datetime type: https://github.com/python/cpython/blob/master/Lib/datetime.py#L1578 But in the C source, it is created from type(self): https://github.com/python/cpython/blob/master/Modules/_datetimemodule.c#L5046 I think the second should be the preferred behavior, so the datetime.py source should be updated to reflect that it's calling self.__class__(...) rather than datetime(...). I can prepare a PR if this would be desirable. (That said, I'm not 100% clear under what circumstances the code in datetime.py is actually *used*, so I'm not sure how to write tests for it - is datetime.py essentially documentation, or is there a way to explicitly fall back to it?) Per this issue on the pypy3 tracker: https://bitbucket.org/pypy/pypy/issues/2635/datetimereplace-always-returns -- components: Interpreter Core messages: 300377 nosy: p-ganssle priority: normal severity: normal status: open title: datetime.py implementation of .replace inconsistent with C implementation versions: Python 3.5, Python 3.6, Python 3.7 ___ Python tracker <http://bugs.python.org/issue31222> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28641] Describe PEP 495 features in "What's New in Python 3.6" document
Paul G added the comment: I've never written a "What's New" before, but here are the main things I took away from implementing a PEP 495-compliant tzinfo class: - The `fold` attribute is the SECOND occurrence of the time, not the first occurrence of the time. In my first pass solution of this, I had this inverted, so I would say it's worth making it very clear which is which, maybe with an example (I'm using full zone names here like those returned by `dateutil.tz.tzwin`): >>> datetime(2011, 11, 6, 1, 30, fold=0, tzinfo=US_EASTERN).tzname() 'Eastern Daylight Time' >>> datetime(2011, 11, 6, 1, 30, fold=1, tzinfo=US_EASTERN).tzname() 'Eastern Standard Time' - Because the default for "fold" is 0, the default for "unspecified" fold has changed from being on the STD side to being on the DST side: >>> datetime(2011, 11, 6, 1, 30, tzinfo=US_EASTERN_NO495).tzname() 'EST' >>> datetime(2011, 11, 6, 1, 30, tzinfo=US_EASTERN_PEP495).tzname() 'EDT' - It is now best practices to implement your own `fromutc()` (I got the impression that in the past it was encouraged that you generally just wrote a `utcoffset()` and `dst()` function. - Comparisons of datetimes have changed such that inter-zone comparisons representing the same wall time and offset will now fail during ambiguous times (depending on the resolution of #28601, the exact semantics of what is an inter-zone comparison should be clarified): >>> dt1 = datetime(2016, 11, 6, 1, 30, fold=1, tzinfo=US_EASTERN) >>> dt2 = datetime(2016, 11, 6, 1, 30, fold=0, tzinfo=US_CENTRAL) >>> dt1 == dt2 False I think the remainder of my insights would have to do with backwards-compatibility and I'm not sure how much relevance they have to "What's New". With regards to the documentation, here are my notes: - One thing that should be made more clear is that arithmetic operations wipe out the `fold` attribute - this behavior and the reasoning behind it should probably be clear in the section on datetime operations, because I think people will be confused by this: >>> from datetime import datetime, timedelta >>> from dateutil import tz >>> dt = datetime(2011, 11, 6, 1, 30, fold=1, tz=gettz('US/Eastern') >>> dt.tzname() 'EST' >>> (dt + timedelta(minutes=1)).tzname() 'EDT' - Not related to the changes in 3.6, but it might also be worth clarifying that `datetime.astimezone()` with no arguments returns a datetime with a fixed offset zone, NOT the local zone (it's somewhat clear, but it could be more explicit): >>> dt.astimezone().tzname() 2011-11-06 01:30:00-5:00 >>> dt.astimezone() - timedelta(hours=5) 2011-11-05 20:30:00-05:00 >>> dt.astimezone(tz.tzlocal()) 2011-11-06 01:30:00-5:00 >>> dt.astimezone(tz.tzlocal()) - timedelta(hours=5) 2011-11-05 20:30:00-04:00 - In the section on "working with datetime objects", GMT1 and GMT2 objects don't support the `fold` attribute. That might be confusing (though there are fold-aware tzinfo objects later in the documentation). - In the section on time.tzname(), the example defines its own GMT1 time zone. It might be clearer to just define GMT1 = datetime.timezone(timedelta(hours=1), "Europe/Prague') rather than create a new fixed offset tzinfo. - The "most implementations of dst() will probably look like one of these two" section should be updated to reflect `fold`, maybe something like this: def dst(self, dt): # Code to set dston and dstoff to the time zone's DST # transition times based on the input dt.year, and expressed # in standard local time. dt_naive = dt.replace(tzinfo=None) if dston <= dt_naive < dstoff: if dt_naive < dston + timedelta(hours=1) and dt.fold: return timedelta(0) else: return timedelta(hours=1) else: return timedelta(0) - The tzinfo.fromutc(dt) documentation suggests that this method is capable of handling non-fixed offset zones. Per #28602, it seems that it should be made clear that all zones implementing `fold` support should implement their own `fromutc` method, as there is a deliberate bug in the algorithm when folds are supported. - This may be slightly confusing: "Note that the datetime instances that differ only by the value of the fold attribute are considered equal in comparisons.", because when I first read this, I assumed it meant that datetime(2011, 11, 6, 1, 30, tzinfo=US_EASTERN) == datetime(2011, 11, 6, 1, 30, fold=1, tzinfo=US_EASTERN), but in fact it either means that *unambiguous* datetimes that di
[issue28602] `tzinfo.fromutc()` fails when used for a fold-aware tzinfo implementation
Paul G added the comment: > After all, how much effort would it save for you in dateutil if you could > reuse the base class fromutc? Realistically, this saves me nothing since I have to re-implement it anyway in in all versions <= Python 3.6 (basically just the exact same algorithm with line 997 replaced with enfold(dt, fold=1) rather than dt.replace(fold=1), but I'd rather it fall back to the standard `fromutc()` in fold-aware versions of Python 3.6. That said, I don't see how it's a big can of worms to open. If you're going to provide `fromutc()` functionality, it should not be deliberately broken. As I mentioned above, I see no actual downside in having `fromutc()` actually work as advertised and as intended. -- ___ Python tracker <http://bugs.python.org/issue28602> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28602] `tzinfo.fromutc()` fails when used for a fold-aware tzinfo implementation
Paul G added the comment: Of the `tzinfo` implementations provided by `python-dateutil`, `tzrange`, `tzstr` (GNU TZ strings), `tzwin` (Windows style time zones) and `tzlocal` all satisfy this condition. These are basically all implementations of default system time zone information. With current implementations `tzfile` and `tzical` also use the invariant algorithm, though theoretically there are edge cases where this will cause problems, and those should have their `fromutc()` adjusted. In any case, I can't think of a single actual downside to this change - all it does is preserve the original behavior of `fromutc()`. As currently implemented, the algorithm is simply wrong when `dst()` is affected by `fold`, and this change would have no effect on zones where `dst()` is *not* affected by fold. -- ___ Python tracker <http://bugs.python.org/issue28602> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28602] `tzinfo.fromutc()` fails when used for a fold-aware tzinfo implementation
New submission from Paul G: After PEP-495, the default value for non-fold-aware datetimes is that they return the DST side, not the STD side (as was the assumption before PEP-495). This invalidates an assumption made in `tz.fromutc()`. See lines 991-1000 of datetime.py: dtdst = dt.dst() if dtdst is None: raise ValueError("fromutc() requires a non-None dst() result") delta = dtoff - dtdst if delta: dt += delta dtdst = dt.dst() if dtdst is None: raise ValueError("fromutc(): dt.dst gave inconsistent " "results; cannot convert") Line 997 (https://github.com/python/cpython/blob/be8de928e5d2f1cd4d4c9c3e6545b170f2b02f1b/Lib/datetime.py#L997) assumes that an ambiguous datetime will return the STD side, not the DST side, and as a result, if you feed it a date in UTC that should resolve to the STD side, it will actually return 1 hour (or whatever the DST offset is) AFTER the ambiguous date that should be returned. If 997 is changed to: dtdst = dt.replace(fold=1).dst() That will not affect fold-naive zones (which are instructed to ignore the `fold` parameter) and restore the original behavior. This will allow fold-aware timezones to be implemented as a wrapper around `fromutc()` rather than a complete re-implementation, e.g.: class FoldAwareTzInfo(datetime.tzinfo): def fromutc(self, dt): dt_wall = super(FoldAwareTzInfo, self).fromutc(dt) is_fold = self._get_fold_status(dt, dt_wall) return dt_wall.replace(fold=is_fold) -- messages: 280007 nosy: belopolsky, p-ganssle, tim.peters priority: normal severity: normal status: open title: `tzinfo.fromutc()` fails when used for a fold-aware tzinfo implementation type: behavior versions: Python 3.6, Python 3.7 ___ Python tracker <http://bugs.python.org/issue28602> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28601] Ambiguous datetime comparisons should use == rather than 'is' for tzinfo comparison
New submission from Paul G: According to PEP495 (https://www.python.org/dev/peps/pep-0495/#aware-datetime-equality-comparison) datetimes are considered not equal if they are an ambiguous time and have different zones. However, currently "interzone comparison" is defined / implemented as the zones being the same object rather than the zones comparing equal. One issue with this is that it actually breaks backwards compatibility of the language, because there doesn't seem to be a way to provide a (backwards-compatible) class that implements folding behavior and has equivalent dates compare equal. An example using python-dateutil: ``` from datetime import datetime from dateutil import tz NYC = tz.gettz('America/New_York') ET = tz.gettz('US/Eastern') dt = datetime(2011, 11, 6, 5, 30, tzinfo=tz.tzutc()) # This is 2011-11-06 01:30 EDT-4 dt_edt = dt.astimezone(ET) dt_nyc = dt.astimezone(NYC) print(dt_nyc == dt_edt) ``` In Python 3.5 that will return True, in Python 3.6 it will return False, even though 'US/Eastern' and 'America/New_York' are the same zone. In this case, I might be able to enforce that these time zones are singletons so that `is` always returns True (though this may have other negative consequences for utility), but even that solution would fall apart for things like `tzrange` and `tzstr`, where you can know that the `dt.utcoffset()`s are going to be identical for ALL values of `dt`, but you can't force the objects to be identical. I would suggest that it be changed to use `__eq__` to determine whether two `tzinfo` objects are the same zone, as this will allow tzinfo providers to create `tzinfo` objects with a consistent behavior between versions in this edge case. -- components: Library (Lib) messages: 280003 nosy: belopolsky, p-ganssle priority: normal severity: normal status: open title: Ambiguous datetime comparisons should use == rather than 'is' for tzinfo comparison type: behavior versions: Python 3.6, Python 3.7 ___ Python tracker <http://bugs.python.org/issue28601> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com