[issue31800] datetime.strptime: Support for parsing offsets with a colon

2017-10-19 Thread Paul G

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

2017-08-16 Thread Paul G

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

2017-08-16 Thread Paul G

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

2016-11-09 Thread Paul G

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

2016-11-03 Thread Paul G

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

2016-11-03 Thread Paul G

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

2016-11-03 Thread Paul G

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

2016-11-03 Thread Paul G

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