Re: [Python-Dev] Status on PEP-431 Timezones

2015-04-15 Thread Lennart Regebro
Yeah, I just realized this. As long as you use timedelta, the
difference is of course not one day, but 24 hours. That solves the
problem, but it is surprising in other ways.

In US/Eastern datetime.datetime(2002, 10, 27, 1, 0) -
datetime.timedelta(1) needs to become datetime.datetime(2002, 10, 26,
2, 0)
(Note the hour change)

I was thinking in calendrial arithmetic, which the datetime module
doesn't need to care about.


On Wed, Apr 15, 2015 at 12:59 AM, Stuart Bishop  wrote:
> On 14 April 2015 at 21:04, Lennart Regebro  wrote:
>> OK, so I realized another thing today, and that is that arithmetic
>> doesn't necessarily round trip.
>>
>> For example, 2002-10-27 01:00 US/Eastern comes both in DST and STD.
>>
>> But 2002-10-27 01:00 US/Eastern STD minus two days is 2002-10-25 01:00
>> US/Eastern DST
>> However, 2002-10-25 01:00 US/Eastern DST plus two days is 2002-10-27
>> 01:00 US/Eastern, but it is ambiguous if you want DST or not DST.
>> And you can't pass in a is_dst flag to __add__, so the arithmatic must
>> just pick one, and the sensible one is to keep to the same DST.
>
 import pytz
 from datetime import datetime, timedelta
 tz = pytz.timezone('US/Eastern')
 dt = tz.localize(datetime(2002, 10, 27, 1, 0), is_dst=False)
 dt2 = tz.normalize(dt - timedelta(days=2) + timedelta(days=2))
 dt == dt2
> True

 tz.normalize(dt - timedelta(days=2))
> datetime.datetime(2002, 10, 25, 2, 0, tzinfo= EDT-1 day, 20:00:00 DST>)
 tz.normalize(tz.normalize(dt - timedelta(days=2)) + timedelta(days=2))
> datetime.datetime(2002, 10, 27, 1, 0, tzinfo= EST-1 day, 19:00:00 STD>)
>
>
> 2002-10-27 01:00 US/Eastern is_dst=0 is after the DST transition
> (EST). Subtracting 48 hours from it crosses the DST boundary and
> should give you 2002-10-27 02:00 US/Eastern is_dst=1, prior to the DST
> transition (EDT). Adding 48 hours again goes past 2002-10-27 01:00
> EDT, crosses the DST boundary, and gives you back 2002-10-27 01:00
> EST.
>
>
> --
> Stuart Bishop 
> http://www.stuartbishop.net/
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Status on PEP-431 Timezones

2015-04-15 Thread Lennart Regebro
OK, so I just had a realization.

Because we want some internal flag to tell if the datetime is in DST
or not, the datetime pickle format will change. And the datetime
pickle format changing is the biggest reason I had against changing
the internal representation to UTC.

So because of this, perhaps we actually *should* change the internal
representation to UTC, because that makes the issues I'm fighting with
now so much simpler. (I'm currently trying to get arithmetic to do the
right thing in all cases, which is crazy complicated).

We can add support to unpickle previous datetimes, but we won't be
able to add forwards compatibility, meaning that pickles saved in
Python 3.5 will not be unpicklable in Python 3.4.

Please discuss.

//Lennart
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Status on PEP-431 Timezones

2015-04-15 Thread Chris Angelico
On Thu, Apr 16, 2015 at 1:00 AM, Lennart Regebro  wrote:
> So because of this, perhaps we actually *should* change the internal
> representation to UTC, because that makes the issues I'm fighting with
> now so much simpler. (I'm currently trying to get arithmetic to do the
> right thing in all cases, which is crazy complicated).

If I understand you correctly, then, an aware datetime would represent
a unique instant in time (modulo relativity), coupled with some
metadata stating what civil timezone it should be understood in terms
of. This is the same as a PostgreSQL "timestamp with time zone" field,
and IMO is a pretty reliable way to do things. So count me as +1 for
this proposal.

Bikeshed: Would arithmetic be based on UTC time or Unix time? It'd be
more logical to describe it as "adding six hours means adding six
hours to the UTC time", but it'd look extremely odd when there's a
leap second.

ChrisA
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Status on PEP-431 Timezones

2015-04-15 Thread Lennart Regebro
On Wed, Apr 15, 2015 at 11:10 AM, Chris Angelico  wrote:
> Bikeshed: Would arithmetic be based on UTC time or Unix time? It'd be
> more logical to describe it as "adding six hours means adding six
> hours to the UTC time", but it'd look extremely odd when there's a
> leap second.

It would ignore leap seconds. If you want to call that unix time or
not is a matter of opinion. Hm. I guess the internal representation
*could* be EPOCH + offset, and local times could be calculated
properties, which could be cached (or possibly calculated at
creation).

//Lennart
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Status on PEP-431 Timezones

2015-04-15 Thread Lennart Regebro
On Wed, Apr 15, 2015 at 11:43 AM, Lennart Regebro  wrote:
> On Wed, Apr 15, 2015 at 11:10 AM, Chris Angelico  wrote:
>> Bikeshed: Would arithmetic be based on UTC time or Unix time? It'd be
>> more logical to describe it as "adding six hours means adding six
>> hours to the UTC time", but it'd look extremely odd when there's a
>> leap second.
>
> It would ignore leap seconds. If you want to call that unix time or
> not is a matter of opinion. Hm. I guess the internal representation
> *could* be EPOCH + offset, and local times could be calculated
> properties, which could be cached (or possibly calculated at
> creation).

In any case there wold probably need to be a PEP on that, and that
means PEP 431 wouldn't make it into 3.5, unless somebody smarter than
me want to take a shot at it.

//Lennart
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Status on PEP-431 Timezones

2015-04-15 Thread Isaac Schwabacher
On 15-04-15, Lennart Regebro  wrote:
> On Wed, Apr 15, 2015 at 11:10 AM, Chris Angelico  wrote:
> > Bikeshed: Would arithmetic be based on UTC time or Unix time? It'd be
> > more logical to describe it as "adding six hours means adding six
> > hours to the UTC time", but it'd look extremely odd when there's a
> > leap second.
> 
> It would ignore leap seconds. If you want to call that unix time or
> not is a matter of opinion. Hm. I guess the internal representation
> *could* be EPOCH + offset, and local times could be calculated
> properties, which could be cached (or possibly calculated at
> creation).

I am on the fence about EPOCH + offset as an internal representation. On the 
one hand, it is conceptually cleaner than the horrible byte-packing that exists 
today, but on the other hand, it has implications for future implementations of 
leap-second-awareness. For instance, offset measures the difference between the 
local time and UTC. But is it honest-to-goodness leap-second aware UTC, or is 
it really Unix time? This could be solved by giving each tzinfo a pointer to 
the UTC from which it is offset, but that sounds like a can of worms we don't 
want to open. But if don't and we store EPOCH + offset, we can't add leap 
second awareness to UTC without corrupting all persisted aware datetimes.

Also, I didn't mention this before because I figured people were getting sick 
of my dumb idea, but another advantage of always caching the offset is that you 
can detect future datetimes that have been corrupted by zoneinfo changes. You 
need both absolute time and offset to be able to do this.

ijs
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Status on PEP-431 Timezones

2015-04-15 Thread Lennart Regebro
On Wed, Apr 15, 2015 at 12:40 PM, Isaac Schwabacher
 wrote:
> I am on the fence about EPOCH + offset as an internal representation. On the 
> one hand, it is conceptually cleaner than the horrible byte-packing that 
> exists today, but on the other hand, it has implications for future 
> implementations of leap-second-awareness. For instance, offset measures the 
> difference between the local time and UTC. But is it honest-to-goodness 
> leap-second aware UTC, or is it really Unix time? This could be solved by 
> giving each tzinfo a pointer to the UTC from which it is offset, but that 
> sounds like a can of worms we don't want to open. But if don't and we store 
> EPOCH + offset, we can't add leap second awareness to UTC without corrupting 
> all persisted aware datetimes.


That's true, with separate values like there is now we can easily
allow 23:59:60 as a timestamp during leap seconds. I'm not entirely
sure it makes a big difference though, I don't think we ever wants to
deal with leap seconds by default.

I don't think we ever want the standard arithmetic deal with leap
seconds anyway.

datetime(2012, 6, 30, 23, 30) + timedelta(seconds=3600) returning
datetime(2012, 7, 1, 0, 29, 59)


I guess leap second implementations should rather have special
functions for arithmethics that deal with this.

//Lennart
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Status on PEP-431 Timezones

2015-04-15 Thread Isaac Schwabacher
On 15-04-15, Lennart Regebro  wrote:
> On Wed, Apr 15, 2015 at 12:40 PM, Isaac Schwabacher
>  wrote:
> > I am on the fence about EPOCH + offset as an internal representation. On 
> > the one hand, it is conceptually cleaner than the horrible byte-packing 
> > that exists today, but on the other hand, it has implications for future 
> > implementations of leap-second-awareness. For instance, offset measures the 
> > difference between the local time and UTC. But is it honest-to-goodness 
> > leap-second aware UTC, or is it really Unix time? This could be solved by 
> > giving each tzinfo a pointer to the UTC from which it is offset, but that 
> > sounds like a can of worms we don't want to open. But if don't and we store 
> > EPOCH + offset, we can't add leap second awareness to UTC without 
> > corrupting all persisted aware datetimes.
> 
> 
> That's true, with separate values like there is now we can easily
> allow 23:59:60 as a timestamp during leap seconds. I'm not entirely
> sure it makes a big difference though, I don't think we ever wants to
> deal with leap seconds by default.
> 
> I don't think we ever want the standard arithmetic deal with leap
> seconds anyway.
> 
> datetime(2012, 6, 30, 23, 30) + timedelta(seconds=3600) returning
> datetime(2012, 7, 1, 0, 29, 59)
> 
> 
> I guess leap second implementations should rather have special
> functions for arithmethics that deal with this.

You need relative timedeltas to mitigate the pain of leap seconds, yes. But as 
soon as you have timedeltas that are capable of representing "this number of 
seconds into the next minute" ("one minute") as opposed to "sixty seconds", 
this isn't so much of a problem. Though of course subtraction will (and 
should!) continue to yield timedelta(seconds=3601).

>From my perspective, the issue is more that the stdlib shouldn't rule out leap 
>seconds. It's reasonable enough to expect users who actually want them to 
>write appropriate tzinfo and timedelta classes, but we don't want to make that 
>impossible the way the old tzinfo interface made DST-aware time zones 
>impossible by insisting that implementers implement a function that wasn't 
>mathematically a function.

I need to think about this more before I can get a real rant going.

ijs
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Status on PEP-431 Timezones

2015-04-15 Thread Stuart Bishop
On 15 April 2015 at 17:00, Lennart Regebro  wrote:
> OK, so I just had a realization.
>
> Because we want some internal flag to tell if the datetime is in DST
> or not, the datetime pickle format will change. And the datetime
> pickle format changing is the biggest reason I had against changing
> the internal representation to UTC.
>
> So because of this, perhaps we actually *should* change the internal
> representation to UTC, because that makes the issues I'm fighting with
> now so much simpler. (I'm currently trying to get arithmetic to do the
> right thing in all cases, which is crazy complicated).

Huh. I didn't think you would need to change any arithmetic (but
haven't looked at this for quite some time). You can already add or
subtract timedeltas to timezone aware datetime instances. The problem
with the existing implementation is the tzinfo instance does not have
enough information to do correct conversions when the time is
ambiguous, so it has to guess. With the addition of the is_dst hint to
the datetime instance, it will no longer need to guess.  Arithmetic
remains 'add the timedelta to the naive datetime, and then punt it to
the tzinfo to make any necessary adjustments' and I thought this would
not need to be changed at all.


> We can add support to unpickle previous datetimes, but we won't be
> able to add forwards compatibility, meaning that pickles saved in
> Python 3.5 will not be unpicklable in Python 3.4.

I don't think this can be avoided entirely. Any ideas I can come up
with that might help are worse than requiring devs to convert their
datetimes to strings in the rare case they need their 3.5 pickles read
with 3.4.


-- 
Stuart Bishop 
http://www.stuartbishop.net/
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Status on PEP-431 Timezones

2015-04-15 Thread Lennart Regebro
On Wed, Apr 15, 2015 at 3:23 PM, Stuart Bishop  wrote:
> Huh. I didn't think you would need to change any arithmetic

Not really, the problem is in keeping the date normalized after each
call, and doing so the right way.

> Arithmetic
> remains 'add the timedelta to the naive datetime, and then punt it to
> the tzinfo to make any necessary adjustments' and I thought this would
> not need to be changed at all.

Just punting it to tzinfo to make adjustments, ie effectively just
doing what normalize() does creates infinite recursion as there is
more arithmetic in there, so it's not quite that simple.

> I don't think this can be avoided entirely. Any ideas I can come up
> with that might help are worse than requiring devs to convert their
> datetimes to strings in the rare case they need their 3.5 pickles read
> with 3.4.

Pickle forward compatibility isn't really expected anyway...
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Status on PEP-431 Timezones

2015-04-15 Thread Chris Angelico
On Thu, Apr 16, 2015 at 1:43 AM, Lennart Regebro  wrote:
> On Wed, Apr 15, 2015 at 11:10 AM, Chris Angelico  wrote:
>> Bikeshed: Would arithmetic be based on UTC time or Unix time? It'd be
>> more logical to describe it as "adding six hours means adding six
>> hours to the UTC time", but it'd look extremely odd when there's a
>> leap second.
>
> It would ignore leap seconds. If you want to call that unix time or
> not is a matter of opinion. Hm. I guess the internal representation
> *could* be EPOCH + offset, and local times could be calculated
> properties, which could be cached (or possibly calculated at
> creation).

I was just talking about leap seconds, here (which Unix time ignores),
not about the internal representation, which is an implementation
detail. If a timedelta is represented as a number of seconds, then
"adding six hours" really means "adding 6*3600 seconds", and most
people would be VERY surprised if one of those is "consumed" by a leap
second; but it ought at least to be acknowledged in the docs.

ChrisA
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Status on PEP-431 Timezones

2015-04-15 Thread Akira Li
Alexander Belopolsky  writes:

> On Wed, Apr 8, 2015 at 3:57 PM, Isaac Schwabacher 
> wrote:
>>
>> On 15-04-08, Alexander Belopolsky wrote:
>> > With datetime, we also have a problem that POSIX APIs don't have to
> deal with: local time
>> > arithmetics. What is t + timedelta(1) when t falls on the day before
> DST change? How would
>> > you set the isdst flag in the result?
>>
>> It's whatever time comes 60*60*24 seconds after t in the same time zone,
> because the timedelta class isn't expressive enough to represent anything
> but absolute time differences (nor should it be, IMO).
>
> This is not what most uses expect.  The expect
>
> datetime(y, m, d, 12, tzinfo=New_York) + timedelta(1)
>
> to be
>
> datetime(y, m, d+1, 12, tzinfo=New_York)

It is incorrect. If you want d+1 for +timedelta(1); use a **naive**
datetime. Otherwise +timedelta(1) is +24h:

  tomorrow = tz.localize(aware_dt.replace(tzinfo=None) + timedelta(1), 
is_dst=None)
  dt_plus24h = tz.normalize(aware_dt + timedelta(1)) # +24h

*tomorrow* and *aware_dt* have the *same* time but it is unknown how
 many hours have passed if the utc offset has changed in between.
*dt_plus24h* may have a different time but there are exactly 24 hours
 have passed between *dt_plush24* and *aware_dt*
http://stackoverflow.com/questions/441147/how-can-i-subtract-a-day-from-a-python-date

___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Status on PEP-431 Timezones

2015-04-15 Thread Akira Li
Lennart Regebro  writes:

> OK, so I realized another thing today, and that is that arithmetic
> doesn't necessarily round trip.
>
> For example, 2002-10-27 01:00 US/Eastern comes both in DST and STD.
>
> But 2002-10-27 01:00 US/Eastern STD minus two days is 2002-10-25 01:00
> US/Eastern DST

"two days" is ambiguous here. It is incorrect if you mean 48 hours (the
difference is 49 hours):

  #!/usr/bin/env python3
  from datetime import datetime, timedelta
  import pytz

  tz = pytz.timezone('US/Eastern')
  then_isdst = False # STD
  then = tz.localize(datetime(2002, 10, 27, 1), is_dst=then_isdst)
  now =  tz.localize(datetime(2002, 10, 25, 1), is_dst=None) # no utc transition
  print((then - now) // timedelta(hours=1))
  # -> 49

> However, 2002-10-25 01:00 US/Eastern DST plus two days is 2002-10-27
> 01:00 US/Eastern, but it is ambiguous if you want DST or not DST.

It is not ambiguous if you know what "two days" *in your particular
application* should mean (`day+2` vs. +48h exactly):

  print(tz.localize(now.replace(tzinfo=None) + timedelta(2), is_dst=then_isdst))
  # -> 2002-10-27 01:00:00-05:00 # +49h
  print(tz.normalize(now + timedelta(2))) # +48h
  # -> 2002-10-27 01:00:00-04:00

Here's a simple mental model that can be used for date arithmetics:

- naive datetime + timedelta(2) == "same time, elapsed hours unknown"
- aware utc datetime + timedelta(2) == "same time, +48h"
- aware datetime with timezone that may have different utc offsets at
different times + timedelta(2) == "unknown time, +48h"

"unknown" means that you can't tell without knowning the specific
timezone.

It ignores leap seconds.

The 3rd case behaves *as if* the calculations are performed using these
steps (the actual implementation may be different):

1. convert an aware datetime
object to utc (dt.astimezone(pytz.utc))
2. do the simple arithmetics using utc time
3. convert the result to the original pytz timezone (utc_dt.astimezone(tz))

you don't need `.localize()`, `.normalize()` calls here.

> And you can't pass in a is_dst flag to __add__, so the arithmatic must
> just pick one, and the sensible one is to keep to the same DST.
>
> That means that:
>
> tz = get_timezone('US/Eastern')
> dt = datetimedatetime(2002, 10, 27, 1, 0, tz=tz, is_dst=False)
> dt2 = dt - 420 + 420
> assert dt == dt2
>
> Will fail, which will be unexpected for most people.
>
> I think there is no way around this, but I thought I should flag for
> it. This is a good reason to do all your date time arithmetic in UTC.
>
> //Lennart

It won't fail:

  from datetime import datetime, timedelta
  import pytz

  tz = pytz.timezone('US/Eastern')
  dt = tz.localize(datetime(2002, 10, 27, 1), is_dst=False)
  delta = timedelta(seconds=420)

  assert dt == tz.normalize(tz.normalize(dt - delta) + delta)

The only reason `tz.normalize()` is used so that tzinfo would be correct
for the resulting datetime object; it does not affect the comparison otherwise:

  assert dt == (dt - delta + delta) #XXX tzinfo may be incorrect
  assert dt == tz.normalize(dt - delta + delta) # correct tzinfo for the final 
result

___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Status on PEP-431 Timezones

2015-04-15 Thread Akira Li
Isaac Schwabacher  writes:
> ...
>
> I know that you can do datetime.now(tz), and you can do datetime(2013,
> 11, 3, 1, 30, tzinfo=zoneinfo('America/Chicago')), but not being able
> to add a time zone to an existing naive datetime is painful (and
> strptime doesn't even let you pass in a time zone). 

`.now(tz)` is correct. `datetime(..., tzinfo=tz)`) is wrong: if tz is a
pytz timezone then you may get a wrong tzinfo (LMT), you should use
`tz.localize(naive_dt, is_dst=False|True|None)` instead.

> ...

___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Status on PEP-431 Timezones

2015-04-15 Thread Isaac Schwabacher
On 15-04-15, Akira Li <[email protected]> wrote:
> Isaac Schwabacher  writes:
> > ...
> >
> > I know that you can do datetime.now(tz), and you can do datetime(2013,
> > 11, 3, 1, 30, tzinfo=zoneinfo('America/Chicago')), but not being able
> > to add a time zone to an existing naive datetime is painful (and
> > strptime doesn't even let you pass in a time zone). 
> 
> `.now(tz)` is correct. `datetime(..., tzinfo=tz)`) is wrong: if tz is a
> pytz timezone then you may get a wrong tzinfo (LMT), you should use
> `tz.localize(naive_dt, is_dst=False|True|None)` instead.

The whole point of this thread is to finalize PEP 431, which fixes the problem 
for which `localize()` and `normalize()` are workarounds. When this is done, 
`datetime(..., tzinfo=tz)` will be correct.

ijs
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Aware datetime from naive local time Was: Status on PEP-431 Timezones

2015-04-15 Thread Akira Li
Alexander Belopolsky  writes:

> Sorry for a truncated message.  Please scroll past the quoted portion.
>
> On Thu, Apr 9, 2015 at 10:21 PM, Alexander Belopolsky <
> [email protected]> wrote:
>
>>
>> On Thu, Apr 9, 2015 at 4:51 PM, Isaac Schwabacher 
>> wrote:
>>
>>> > > > Well, you are right, but at least we do have a localtime utility
>>> hidden in the email package:
>>> > > >
>>> > > > >>> from datetime import *
>>> > > > >>> from email.utils import localtime
>>> > > > >>> print(localtime(datetime.now()))
>>> > > > 2015-04-09 15:19:12.84-04:00
>>> > > >
>>> > > > You can read  for the reasons it
>>> did not make into datetime.
>>> > >
>>> > > But that's restricted to the system time zone. Nothing good ever
>>> comes from the system time zone...
>>> >
>>> > Let's solve one problem at a time. ...
>>>
>>> PEP 431 proposes to import zoneinfo into the stdlib, ...
>>
>>
>> I am changing the subject so that we can focus on one question without
>> diverting to PEP-size issues that are better suited for python ideas.
>>
>> I would like to add a functionality to the datetime module that would
>> solve a seemingly simple problem: given a naive datetime instance assumed
>> to be in local time, construct the corresponding aware datetime object with
>> tzinfo set to an appropriate fixed offset datetime.timezone instance.
>>
>> Python 3 has this functionality implemented in the email package since
>> version 3.3, and it appears to work well even
>> in the ambiguous hour
>>
>> >>> from email.utils import localtime
>> >>> from datetime import datetime
>> >>> localtime(datetime(2014,11,2,1,30)).strftime('%c %z %Z')
>> 'Sun Nov  2 01:30:00 2014 -0400 EDT'
>> >>> localtime(datetime(2014,11,2,1,30), isdst=0).strftime('%c %z %Z')
>> 'Sun Nov  2 01:30:00 2014 -0500 EST'
>>
>> However, in a location with a more interesting history, you can get a
>> situation that
>>
>
> would look like this in the zoneinfo database:
>
> $ zdump -v  -c 1992 Europe/Kiev
> ...
> Europe/Kiev  Sat Mar 24 22:59:59 1990 UTC = Sun Mar 25 01:59:59 1990 MSK
> isdst=0
> Europe/Kiev  Sat Mar 24 23:00:00 1990 UTC = Sun Mar 25 03:00:00 1990 MSD
> isdst=1
> Europe/Kiev  Sat Jun 30 21:59:59 1990 UTC = Sun Jul  1 01:59:59 1990 MSD
> isdst=1
> Europe/Kiev  Sat Jun 30 22:00:00 1990 UTC = Sun Jul  1 01:00:00 1990 EEST
> isdst=1
> Europe/Kiev  Sat Sep 28 23:59:59 1991 UTC = Sun Sep 29 02:59:59 1991 EEST
> isdst=1
> Europe/Kiev  Sun Sep 29 00:00:00 1991 UTC = Sun Sep 29 02:00:00 1991 EET
> isdst=0
> ...
>
> Look what happened on July 1, 1990.  At 2 AM, the clocks in Ukraine were
> moved back one hour.  So times like 01:30 AM happened twice there on that
> day.  Let's see how Python handles this situation
>
> $ TZ=Europe/Kiev python3
 from email.utils import localtime
 from datetime import datetime
 localtime(datetime(1990,7,1,1,30)).strftime('%c %z %Z')
> 'Sun Jul  1 01:30:00 1990 +0400 MSD'
>
> So far so good, I've got the first of the two 01:30AM's.  But what if I
> want the other 01:30AM?  Well,
>
 localtime(datetime(1990,7,1,1,30), isdst=0).strftime('%c %z %Z')
> 'Sun Jul  1 01:30:00 1990 +0300 EEST'
>
> gives me "the other 01:30AM", but it is counter-intuitive: I have to ask
> for the standard (winter)  time to get the daylight savings (summer) time.
>

It looks incorrect. Here's the corresponding pytz code:

  from datetime import datetime
  import pytz

  tz = pytz.timezone('Europe/Kiev')
  print(tz.localize(datetime(1990, 7, 1, 1, 30), is_dst=False).strftime('%c %z 
%Z'))
  # -> Sun Jul  1 01:30:00 1990 +0300 EEST
  print(tz.localize(datetime(1990, 7, 1, 1, 30), is_dst=True).strftime('%c %z 
%Z'))
  # -> Sun Jul  1 01:30:00 1990 +0400 MSD
  
See also "Enhance support for end-of-DST-like ambiguous time" [1]

[1] https://bugs.launchpad.net/pytz/+bug/1378150

`email.utils.localtime()` is broken:

  from datetime import datetime
  from email.utils import localtime

  print(localtime(datetime(1990, 7, 1, 1, 30)).strftime('%c %z %Z'))
  # -> Sun Jul  1 01:30:00 1990 +0300 EEST
  print(localtime(datetime(1990, 7, 1, 1, 30), isdst=0).strftime('%c %z %Z'))
  # -> Sun Jul  1 01:30:00 1990 +0300 EEST
  print(localtime(datetime(1990, 7, 1, 1, 30), isdst=1).strftime('%c %z %Z'))
  # -> Sun Jul  1 01:30:00 1990 +0300 EEST
  print(localtime(datetime(1990, 7, 1, 1, 30), isdst=-1).strftime('%c %z %Z'))
  # -> Sun Jul  1 01:30:00 1990 +0300 EEST
  

Versions:

  $ ./python -V
  Python 3.5.0a3+
  $ dpkg -s tzdata | grep -i version
  Version: 2015b-0ubuntu0.14.04

> The uncertainty about how to deal with the repeated hour was the reason why
> email.utils.localtime-like  interface did not make it to the datetime
> module.

"repeated hour" (time jumps back) can be treated like a end-of-DST
transition, to resolve ambiguities [1].

> The main objection to the isdst flag was that in most situations,
> determining whether DST is in effect is as hard as finding the UTC offset,
> so reducing the problem of finding the 

Re: [Python-Dev] Status on PEP-431 Timezones

2015-04-15 Thread Stuart Bishop
On 15 April 2015 at 21:51, Lennart Regebro  wrote:
> On Wed, Apr 15, 2015 at 3:23 PM, Stuart Bishop  
> wrote:

> Just punting it to tzinfo to make adjustments, ie effectively just
> doing what normalize() does creates infinite recursion as there is
> more arithmetic in there, so it's not quite that simple.

This sounds familiar. Its infinite recursion if the tzinfo does its
calculations using localized datetimes. If the tzinfo is stripped for
the calculations, there is no tzinfo to recurse into. At least this
was how I hoped it would work, and it sucks if it doesn't. You could
be right that using the UTC representation internally for datetimes
with a tzinfo makes the most sense.

-- 
Stuart Bishop 
http://www.stuartbishop.net/
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Aware datetime from naive local time Was: Status on PEP-431 Timezones

2015-04-15 Thread Akira Li
Alexander Belopolsky  writes:

> ...
> For most world locations past discontinuities are fairly well documented
> for at least a century and future changes are published with at least 6
> months lead time.

It is important to note that the different versions of the tz database
may lead to different tzinfo (utc offset, tzname) even for *past* dates.

i.e., (lt, tzid, isdst) is not enough because the result for (lt,
tzid(2015b), isdst) may be different from (lt, tzid(X), isdst)
where

lt = local time e.g., naive datetime
tzid = timezone from the tz database e.g., Europe/Kiev
isdst = a boolean flag for disambiguation
X != 2015b

In other words, a fixed utc offset might not be sufficient even for past
dates.

>...
> Moreover, a program that rejects invalid times on input, but stores them
> for a long time may see its database silently corrupted after a zoneinfo
> update.

> Now it is time to make specific proposal.  I would like to extend
> datetime.astimezone() method to work on naive datetime instances.  Such
> instances will be assumed to be in local time and discontinuities will be
> handled as follows:
>
>
> 1. wall(t) == lt has a single solution.  This is the trivial case and
> lt.astimezone(utc) and lt.astimezone(utc, which=i)  for i=0,1 should return
> that solution.
>
> 2. wall(t) == lt has two solutions t1 and t2 such that t1 < t2. In this
> case lt.astimezone(utc) == lt.astimezone(utc, which=0) == t1 and
>  lt.astimezone(utc, which=1) == t2.

In pytz terms: `which = not isdst` (end-of-DST-like transition: isdst
changes from True to False in the direction of utc time).

It resolves AmbiguousTimeError raised by `tz.localize(naive, is_dst=None)`.

> 3. wall(t) == lt has no solution.  This happens when there is UTC time t0
> such that wall(t0) < lt and wall(t0+epsilon) > lt (a positive discontinuity
> at time t0). In this case lt.astimezone(utc) should return t0 + lt -
> wall(t0).  I.e., we ignore the discontinuity and extend wall(t) linearly
> past t0.  Obviously, in this case the invariant wall(lt.astimezone(utc)) ==
> lt won't hold.   The "which" flag should be handled as follows:
>  lt.astimezone(utc) == lt.astimezone(utc, which=0) and lt.astimezone(utc,
> which=0) == t0 + lt - wall(t0+eps).

It is inconsistent with the previous case: here `which = isdst` but
`which = not isdst` above.

`lt.astimezone(utc, which=0) == t0 + lt - wall(t0+eps)` corresponds to:

  result = tz.normalize(tz.localize(lt, isdst=False))

i.e., `which = isdst` (t0 is at the start of DST and therefore isdst
changes from False to True).

It resolves NonExistentTimeError raised by `tz.localize(naive,
is_dst=None)`. start-of-DST-like transition ("Spring forward").

For example,

  from datetime import datetime, timedelta
  import pytz
  
  tz = pytz.timezone('America/New_York')
  # 2am -- non-existent time
  print(tz.normalize(tz.localize(datetime(2015, 3, 8, 2), is_dst=False)))
  # -> 2015-03-08 03:00:00-04:00 # after the jump (wall(t0+eps))
  print(tz.localize(datetime(2015, 3, 8, 3), is_dst=None))
  # -> 2015-03-08 03:00:00-04:00 # same time, unambiguous
  # 2:01am -- non-existent time
  print(tz.normalize(tz.localize(datetime(2015, 3, 8, 2, 1), is_dst=False)))
  # -> 2015-03-08 03:01:00-04:00
  print(tz.localize(datetime(2015, 3, 8, 3, 1), is_dst=None))
  # -> 2015-03-08 03:01:00-04:00 # same time, unambiguous
  # 2:59am non-existent time
  dt = tz.normalize(tz.localize(datetime(2015, 3, 8, 2, 59), is_dst=True))
  print(dt)
  # -> 2015-03-08 01:59:00-05:00 # before the jump (wall(t0-eps))
  print(tz.normalize(dt + timedelta(minutes=1)))
  # -> 2015-03-08 03:00:00-04:00


> With the proposed features in place, one can use the naive code
>
> t =  lt.astimezone(utc)
>
> and get predictable behavior in all cases and no crashes.
>
> A more sophisticated program can be written like this:
>
> t1 = lt.astimezone(utc, which=0)
> t2 = lt.astimezone(utc, which=1)
> if t1 == t2:
> t = t1
> elif t2 > t1:
> # ask the user to pick between t1 and t2 or raise
> AmbiguousLocalTimeError
> else:
> t = t1
> # warn the user that time was invalid and changed or raise
> InvalidLocalTimeError

___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Aware datetime from naive local time Was: Status on PEP-431 Timezones

2015-04-15 Thread Alexander Belopolsky
On Wed, Apr 15, 2015 at 4:46 PM, Akira Li <[email protected]> wrote:

> > Look what happened on July 1, 1990.  At 2 AM, the clocks in Ukraine were
> > moved back one hour.  So times like 01:30 AM happened twice there on that
> > day.  Let's see how Python handles this situation
> >
> > $ TZ=Europe/Kiev python3
>  from email.utils import localtime
>  from datetime import datetime
>  localtime(datetime(1990,7,1,1,30)).strftime('%c %z %Z')
> > 'Sun Jul  1 01:30:00 1990 +0400 MSD'
> >
> > So far so good, I've got the first of the two 01:30AM's.  But what if I
> > want the other 01:30AM?  Well,
> >
>  localtime(datetime(1990,7,1,1,30), isdst=0).strftime('%c %z %Z')
> > 'Sun Jul  1 01:30:00 1990 +0300 EEST'
> >
> > gives me "the other 01:30AM", but it is counter-intuitive: I have to ask
> > for the standard (winter)  time to get the daylight savings (summer)
> time.
> >
>
> It looks incorrect. Here's the corresponding pytz code:
>
>   from datetime import datetime
>   import pytz
>
>   tz = pytz.timezone('Europe/Kiev')
>   print(tz.localize(datetime(1990, 7, 1, 1, 30),
> is_dst=False).strftime('%c %z %Z'))
>   # -> Sun Jul  1 01:30:00 1990 +0300 EEST
>   print(tz.localize(datetime(1990, 7, 1, 1, 30), is_dst=True).strftime('%c
> %z %Z'))
>   # -> Sun Jul  1 01:30:00 1990 +0400 MSD
>
> See also "Enhance support for end-of-DST-like ambiguous time" [1]
>
> [1] https://bugs.launchpad.net/pytz/+bug/1378150
>
> `email.utils.localtime()` is broken:
>

If you think there is a bug in email.utils.localtime - please open an issue
at .


>
>   from datetime import datetime
>   from email.utils import localtime
>
>   print(localtime(datetime(1990, 7, 1, 1, 30)).strftime('%c %z %Z'))
>   # -> Sun Jul  1 01:30:00 1990 +0300 EEST
>   print(localtime(datetime(1990, 7, 1, 1, 30), isdst=0).strftime('%c %z
> %Z'))
>   # -> Sun Jul  1 01:30:00 1990 +0300 EEST
>   print(localtime(datetime(1990, 7, 1, 1, 30), isdst=1).strftime('%c %z
> %Z'))
>   # -> Sun Jul  1 01:30:00 1990 +0300 EEST
>   print(localtime(datetime(1990, 7, 1, 1, 30), isdst=-1).strftime('%c %z
> %Z'))
>   # -> Sun Jul  1 01:30:00 1990 +0300 EEST
>
>
> Versions:
>
>   $ ./python -V
>   Python 3.5.0a3+
>   $ dpkg -s tzdata | grep -i version
>   Version: 2015b-0ubuntu0.14.04
>
> > The uncertainty about how to deal with the repeated hour was the reason
> why
> > email.utils.localtime-like  interface did not make it to the datetime
> > module.
>
> "repeated hour" (time jumps back) can be treated like a end-of-DST
> transition, to resolve ambiguities [1].


I don't understand what you are complaining about.  It is quite possible
that pytz uses is_dst flag differently from the way email.utils.localtime
uses isdst.

I was not able to find a good description of what is_dst means in pytz, but
localtime's isdst is documented as follows:

a positive or zero value for *isdst* causes localtime to
presume initially that summer time (for example, Daylight Saving Time)
is or is not (respectively) in effect for the specified time.

Can you demonstrate that email.utils.localtime does not behave as
documented?
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Status on PEP-431 Timezones

2015-04-15 Thread Alexander Belopolsky
On Wed, Apr 15, 2015 at 5:28 PM, Stuart Bishop 
wrote:
>
> On 15 April 2015 at 21:51, Lennart Regebro  wrote:
> > On Wed, Apr 15, 2015 at 3:23 PM, Stuart Bishop 
wrote:
>
> > Just punting it to tzinfo to make adjustments, ie effectively just
> > doing what normalize() does creates infinite recursion as there is
> > more arithmetic in there, so it's not quite that simple.
>
> This sounds familiar. Its infinite recursion if the tzinfo does its
> calculations using localized datetimes. If the tzinfo is stripped for
> the calculations, there is no tzinfo to recurse into. At least this
> was how I hoped it would work, and it sucks if it doesn't. You could
> be right that using the UTC representation internally for datetimes
> with a tzinfo makes the most sense.

There is no infinite recursion in the way datetime module deals with zone
conversions.   However, implementors of tzinfo subclasses often overlook
the fact that datetime module design mandates specific rules for what
utcoffset() should return for the missing and ambiguous hours. Granted, the
relevant section in the manual [1] is not an easy read and in fact for a
long time that documentation itself was displaying a buggy implementation
of the LocalTimezone class. [2]

Understanding how the design works requires a bit of algebra [3], but I
strongly recommend that anyone trying to improve the timezones support in
the datetime module, print out those 200 lines of comments and go through
them with a pencil following the proofs.

Note that one of the key assumptions [3.2] in that write-up does not hold
in real life.  The assumption is that "standard time" offset does not
depend on the point in time.  However, I do believe that this assumption
can be relaxed without invalidating the main result.   I believe we can
still have unambiguous fromutc() as long as standard time offset does not
change "too often."  Basically, if we (generously)  allow utcoffset to vary
from -24h to +24h, then a "sane" zone can be defined as the one where
utcoffset changes at most once in any 48 hour period.

If I am right about this and the algebra works out, then we don't need to
change datetime module design to properly support all world timezones.

[1] https://docs.python.org/3/library/datetime.html#datetime.tzinfo.fromutc
[2] http://bugs.python.org/issue9063
[3] https://hg.python.org/cpython/file/132b5376bf34/Lib/datetime.py#l1935
[3.2] https://hg.python.org/cpython/file/132b5376bf34/Lib/datetime.py#l1948
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Status on PEP-431 Timezones

2015-04-15 Thread Akira Li
Isaac Schwabacher  writes:

> On 15-04-15, Akira Li <[email protected]> wrote:
>> Isaac Schwabacher  writes:
>> > ...
>> >
>> > I know that you can do datetime.now(tz), and you can do datetime(2013,
>> > 11, 3, 1, 30, tzinfo=zoneinfo('America/Chicago')), but not being able
>> > to add a time zone to an existing naive datetime is painful (and
>> > strptime doesn't even let you pass in a time zone). 
>> 
>> `.now(tz)` is correct. `datetime(..., tzinfo=tz)`) is wrong: if tz is a
>> pytz timezone then you may get a wrong tzinfo (LMT), you should use
>> `tz.localize(naive_dt, is_dst=False|True|None)` instead.
>
> The whole point of this thread is to finalize PEP 431, which fixes the
> problem for which `localize()` and `normalize()` are workarounds. When
> this is done, `datetime(..., tzinfo=tz)` will be correct.
>
> ijs

The input time is ambiguous. Even if we assume PEP 431 is implemented in
some form, your code is still missing isdst parameter (or the
analog). PEP 431 won't fix it; it can't resolve the ambiguity by
itself. Notice is_dst paramter in the `tz.localize()` call (current
API).

.now(tz) works even during end-of-DST transitions (current API) when the
local time is ambiguous.

___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Status on PEP-431 Timezones

2015-04-15 Thread Isaac Schwabacher
On 15-04-15, Akira Li <[email protected]> wrote:
> Isaac Schwabacher  writes:
> 
> > On 15-04-15, Akira Li <[email protected]> wrote:
> >> Isaac Schwabacher  writes:
> >> > ...
> >> >
> >> > I know that you can do datetime.now(tz), and you can do datetime(2013,
> >> > 11, 3, 1, 30, tzinfo=zoneinfo('America/Chicago')), but not being able
> >> > to add a time zone to an existing naive datetime is painful (and
> >> > strptime doesn't even let you pass in a time zone). 
> >> 
> >> `.now(tz)` is correct. `datetime(..., tzinfo=tz)`) is wrong: if tz is a
> >> pytz timezone then you may get a wrong tzinfo (LMT), you should use
> >> `tz.localize(naive_dt, is_dst=False|True|None)` instead.
> >
> > The whole point of this thread is to finalize PEP 431, which fixes the
> > problem for which `localize()` and `normalize()` are workarounds. When
> > this is done, `datetime(..., tzinfo=tz)` will be correct.
> >
> > ijs
> 
> The input time is ambiguous. Even if we assume PEP 431 is implemented in
> some form, your code is still missing isdst parameter (or the
> analog). PEP 431 won't fix it; it can't resolve the ambiguity by
> itself. Notice is_dst paramter in the `tz.localize()` call (current
> API).

...yeah, I forgot to throw that in there. It was supposed to be there all 
along. Nothing to see here, move along.

> .now(tz) works even during end-of-DST transitions (current API) when the
> local time is ambiguous.

I know that. That's what I was complaining about-- I was trying to talk about 
how astimezone() was going to be inadequate even after the PEP was implemented 
because it couldn't turn naive datetimes into aware ones, and people were 
giving examples that started with aware datetimes generated by now(tz), which 
completely went around the point I was trying to make. But it looks like 
astimezone() is going to grow an is_dst parameter, and everything will be OK.

ijs
___
Python-Dev mailing list
[email protected]
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Python3 Stable ABI

2015-04-15 Thread Steve Dower
I don't see any obvious issues, but there may be some that don't need to be 
marked stable.

Given that a mismatch here will cause build errors for users, I'm +1 on 
checking this in.

Cheers,
Steve

Top-posted from my Windows Phone

From: Zachary Ware
Sent: ‎4/‎13/‎2015 17:29
To: Python-Dev
Subject: [Python-Dev] Python3 Stable ABI

In issue23903, I've created a script that will produce PC/python3.def
by scraping the header files in Include.  There are are many many
discrepencies between what my script generates and what is currently
in the repository (diff below), but in every case I've checked the
script has been right: what the script finds is actually exported as
part of the limited API, but due to not being in the .def file it's
not actually exported from python3.dll.  Almost all of the differences
are things that the script found that weren't present, but there are a
couple things going the other way.

The point of this message is to ask everybody who maintains anything
in C to take a look through and make sure everything in their area is
properly guarded (or not) by Py_LIMITED_API.  Alternately, if somebody
can find a bug in my script and brain that's finding too much stuff,
that would be great too.

Ideally, after this is all settled I'd like to add the script to both
the Makefile and the Windows build system, such that PC/python3.def is
always kept up to date and flags changes that weren't meant to be
made.

Regards,
--
Zach

(I'm afraid Gmail might mangle this beyond recognition, you can find the diff at
http://bugs.python.org/review/23903/diff/14549/PC/python3.def
if it does.)

diff -r 24f2c0279120 PC/python3.def
--- a/PC/python3.defMon Apr 13 15:51:59 2015 -0500
+++ b/PC/python3.defMon Apr 13 16:10:34 2015 -0500
@@ -1,13 +1,15 @@
 ; This file specifies the import forwarding for python3.dll
 ; It is used when building python3dll.vcxproj
+; Generated by python3defgen.py, DO NOT modify directly!
 LIBRARY"python3"
 EXPORTS
+  PyAST_FromNode=python35.PyAST_FromNode
+  PyAST_FromNodeObject=python35.PyAST_FromNodeObject
+  PyAST_Validate=python35.PyAST_Validate
   PyArg_Parse=python35.PyArg_Parse
   PyArg_ParseTuple=python35.PyArg_ParseTuple
   PyArg_ParseTupleAndKeywords=python35.PyArg_ParseTupleAndKeywords
   PyArg_UnpackTuple=python35.PyArg_UnpackTuple
-  PyArg_VaParse=python35.PyArg_VaParse
-  PyArg_VaParseTupleAndKeywords=python35.PyArg_VaParseTupleAndKeywords
   PyArg_ValidateKeywordArguments=python35.PyArg_ValidateKeywordArguments
   PyBaseObject_Type=python35.PyBaseObject_Type DATA
   PyBool_FromLong=python35.PyBool_FromLong
@@ -39,7 +41,6 @@
   PyCFunction_GetFlags=python35.PyCFunction_GetFlags
   PyCFunction_GetFunction=python35.PyCFunction_GetFunction
   PyCFunction_GetSelf=python35.PyCFunction_GetSelf
-  PyCFunction_New=python35.PyCFunction_New
   PyCFunction_NewEx=python35.PyCFunction_NewEx
   PyCFunction_Type=python35.PyCFunction_Type DATA
   PyCallIter_New=python35.PyCallIter_New
@@ -58,6 +59,7 @@
   PyCapsule_SetPointer=python35.PyCapsule_SetPointer
   PyCapsule_Type=python35.PyCapsule_Type DATA
   PyClassMethodDescr_Type=python35.PyClassMethodDescr_Type DATA
+  PyCmpWrapper_Type=python35.PyCmpWrapper_Type DATA
   PyCodec_BackslashReplaceErrors=python35.PyCodec_BackslashReplaceErrors
   PyCodec_Decode=python35.PyCodec_Decode
   PyCodec_Decoder=python35.PyCodec_Decoder
@@ -68,6 +70,7 @@
   PyCodec_IncrementalEncoder=python35.PyCodec_IncrementalEncoder
   PyCodec_KnownEncoding=python35.PyCodec_KnownEncoding
   PyCodec_LookupError=python35.PyCodec_LookupError
+  PyCodec_NameReplaceErrors=python35.PyCodec_NameReplaceErrors
   PyCodec_Register=python35.PyCodec_Register
   PyCodec_RegisterError=python35.PyCodec_RegisterError
   PyCodec_ReplaceErrors=python35.PyCodec_ReplaceErrors
@@ -122,6 +125,7 @@
   PyErr_Fetch=python35.PyErr_Fetch
   PyErr_Format=python35.PyErr_Format
   PyErr_FormatV=python35.PyErr_FormatV
+  PyErr_GetExcInfo=python35.PyErr_GetExcInfo
   PyErr_GivenExceptionMatches=python35.PyErr_GivenExceptionMatches
   PyErr_NewException=python35.PyErr_NewException
   PyErr_NewExceptionWithDoc=python35.PyErr_NewExceptionWithDoc
@@ -132,14 +136,25 @@
   PyErr_PrintEx=python35.PyErr_PrintEx
   PyErr_ProgramText=python35.PyErr_ProgramText
   PyErr_Restore=python35.PyErr_Restore
+  PyErr_SetExcFromWindowsErr=python35.PyErr_SetExcFromWindowsErr
+  
PyErr_SetExcFromWindowsErrWithFilename=python35.PyErr_SetExcFromWindowsErrWithFilename
+  
PyErr_SetExcFromWindowsErrWithFilenameObject=python35.PyErr_SetExcFromWindowsErrWithFilenameObject
+  
PyErr_SetExcFromWindowsErrWithFilenameObjects=python35.PyErr_SetExcFromWindowsErrWithFilenameObjects
+  PyErr_SetExcInfo=python35.PyErr_SetExcInfo
+  PyErr_SetExcWithArgsKwargs=python35.PyErr_SetExcWithArgsKwargs
   PyErr_SetFromErrno=python35.PyErr_SetFromErrno
   PyErr_SetFromErrnoWithFilename=python35.PyErr_SetFromErrnoWithFilename
   
PyErr_S