homepage

This issue tracker has been migrated to GitHub , and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Non-naive time comparison throws naive time error
Type: behavior Stage: resolved
Components: Versions: Python 3.2, Python 3.3, Python 2.7
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: Chris.Bergstresser, belopolsky, greg.weller, python-dev, r.david.murray
Priority: normal Keywords: easy, patch

Created on 2012年05月09日 22:11 by Chris.Bergstresser, last changed 2022年04月11日 14:57 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
14766.patch greg.weller, 2012年05月10日 11:55 review
14766.patch greg.weller, 2012年05月10日 23:10 review
Messages (10)
msg160314 - (view) Author: Chris Bergstresser (Chris.Bergstresser) Date: 2012年05月09日 22:11
The datetime module says:
An object d of type time or datetime may be naive or aware. d is aware if d.tzinfo is not None and d.tzinfo.utcoffset(d) does not return None. If d.tzinfo is None, or if d.tzinfo is not None but d.tzinfo.utcoffset(d) returns None, d is naive.
However, I can create two non-naive timezones (under this definition) which throw an exception when they're compared, because one is being considered offset-naive:
>>> import pytz, datetime
>>> UTC_TZ = pytz.utc
>>> EASTERN_TZ = pytz.timezone('America/New_York')
>>> d1 = datetime.time(10, tzinfo = UTC_TZ)
>>> d1
datetime.time(10, 0, tzinfo=<UTC>)
>>> d1.tzinfo
<UTC>
>>> d1.utcoffset(d1)
datetime.timedelta(0)
>>> d2 = datetime.time(10, tzinfo = EASTERN_TZ)
>>> d2
datetime.time(10, 0, tzinfo=<DstTzInfo 'America/New_York' EST-1 day, 19:00:00 STD>)
>>> d2.tzinfo
<DstTzInfo 'America/New_York' EST-1 day, 19:00:00 STD>
>>> d2.tzinfo.utcoffset(d2)
datetime.timedelta(-1, 68400)
>>> d1 < d2
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: can't compare offset-naive and offset-aware times
msg160315 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2012年05月09日 22:56
An equivalent test using python 3.2's datetime.timezone works fine. Are you sure it isn't a bug in pytz?
msg160316 - (view) Author: Chris Bergstresser (Chris.Bergstresser) Date: 2012年05月09日 23:44
It doesn't seem to be a bug in pytz. AFAICT, the only methods that get called during the time comparison is "utcoffset" on the UTC timezone, and "utcoffset" on the New York timezone.
Looking closer at it, it seems that Python is calling d1.tzinfo.utcoffset(None), rather than d1.tzinfo.utcoffset(d1). This is a problem, because the New York timezone cannot calculate the utcoffset without knowing what date it's calculating. As a result, it returns None rather than potentially guessing wrong.
msg160317 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2012年05月10日 00:07
Ah. datetime.timezone wouldn't have that issue since it doesn't deal with DST.
The 3.3 python version of datetime calls utcoffset in the same way as you describe, and it is supposed to have the same behavior as the C version, so probably 3.2/3.3 has the bug as well. (It does look like a bug to me.)
Note that 2.6 is in security fix only mode, so this can only get corrected in 2.7 and 3.2/3.3.
I'm surprised this hasn't been reported before.
msg160335 - (view) Author: Greg Weller (greg.weller) Date: 2012年05月10日 11:55
I think this is a documentation bug. The criteria for datetime and time objects being aware are slightly different. A datetime object d is aware if d.tzinfo.utcoffset(d) does not return None, while a time object t is aware if t.tzinfo.utcoffset(None) does not return None (time objects call utcoffset with None while datetime objects call utcoffset with self).
This accounts for the TypeError in the original example:
>>> import pytz, datetime
>>> UTC_TZ = pytz.utc
>>> EASTERN_TZ = pytz.timezone('America/New_York')
>>> d1 = datetime.time(10, tzinfo=UTC_TZ)
>>> d2 = datetime.time(10, tzinfo=EASTERN_TZ)
>>> repr(d1.tzinfo.utcoffset(None))
'datetime.timedelta(0)'
>>> repr(d2.tzinfo.utcoffset(None))
'None'
>>> d1 < d2
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
TypeError: can't compare offset-naive and offset-aware times
It looks like this example is flawed according to http://pytz.sourceforge.net/ : "Unfortunately using the tzinfo argument of the standard datetime constructors ‘’does not work’’ with pytz for many timezones. It is safe for timezones without daylight savings trasitions though, such as UTC." (If you think about it, the error still makes sense: the UTC time is aware and the eastern time is naive -- any DST time object has to be naive -- but this has more to do with pytz).
It doesn't make sense to have time objects pass self to utcoffset because utcoffset expects a datetime object. You shouldn't be able to infer what the UTC offset is from a time object unless the offset is constant, in which case you don't even need the time object. If the UTC offset isn't constant, you need the date, which a time object doesn't have. I think this is the logic behind having datetime objects call utcoffset(self) and time objects call utcoffset(None).
I've attached a small patch for the documentation.
msg160342 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2012年05月10日 12:53
My, that's embarrassing. I somehow entirely missed the fact that we were dealing with times and not dates here.
What you say makes sense to me, and the doc patch looks good.
msg160351 - (view) Author: Chris Bergstresser (Chris.Bergstresser) Date: 2012年05月10日 15:14
That patch fixes the documentation there, but the description at the top of the distinction between naive and aware time objects at the top datetime module is still wrong. Here it is:
-----------------
There are two kinds of date and time objects: "naive" and "aware". This distinction refers to whether the object has any notion of time zone, daylight saving time, or other kind of algorithmic or political time adjustment. Whether a naive datetime object represents Coordinated Universal Time (UTC), local time, or time in some other timezone is purely up to the program, just like it’s up to the program whether a particular number represents metres, miles, or mass. Naive datetime objects are easy to understand and to work with, at the cost of ignoring some aspects of reality.
------------------
The distinction is not whether the object has any notion of "time zone, daylight saving time, or other kind of algorithmic or political time adjustment", but instead whether, in the context it's being used, it can calculate an offset to UTC. A naive time can be used to create an aware datetime.
msg160380 - (view) Author: Greg Weller (greg.weller) Date: 2012年05月10日 23:10
I agree that the language in the quoted paragraph makes it sound as if any object with a non-None tzinfo is aware, which isn't the case. I've changed the first couple sentences to, I think, better reflect what characterizes an object as being aware.
msg160676 - (view) Author: Roundup Robot (python-dev) (Python triager) Date: 2012年05月15日 02:33
New changeset 28ed782949f9 by R David Murray in branch '3.2':
#14766: Add correct algorithm for when a 'time' object is naive.
http://hg.python.org/cpython/rev/28ed782949f9
New changeset b1e03e863386 by R David Murray in branch '3.2':
#14766: Reflow the altered paragraphs.
http://hg.python.org/cpython/rev/b1e03e863386
New changeset 6ff172db8114 by R David Murray in branch 'default':
Merge #14766: Add correct algorithm for when a 'time' object is naive.
http://hg.python.org/cpython/rev/6ff172db8114
New changeset 5d1b32e33e67 by R David Murray in branch '2.7':
#14766: Add correct algorithm for when a 'time' object is naive.
http://hg.python.org/cpython/rev/5d1b32e33e67
New changeset a002638919d8 by R David Murray in branch '2.7':
#14766: Reflow the altered paragraphs.
http://hg.python.org/cpython/rev/a002638919d8 
msg160678 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2012年05月15日 02:38
I reformatted the first hunk a bit, hopefully to make it even a little bit clearer. We're still punting the actual definition to the later section, but I think that's appropriate.
Thanks for the patch, Greg.
History
Date User Action Args
2022年04月11日 14:57:30adminsetgithub: 58971
2012年05月15日 02:38:05r.david.murraysetstatus: open -> closed
resolution: fixed
messages: + msg160678

stage: needs patch -> resolved
2012年05月15日 02:33:48python-devsetnosy: + python-dev
messages: + msg160676
2012年05月10日 23:10:38greg.wellersetfiles: + 14766.patch

messages: + msg160380
2012年05月10日 15:14:47Chris.Bergstressersetmessages: + msg160351
2012年05月10日 12:53:50r.david.murraysetmessages: + msg160342
2012年05月10日 11:55:28greg.wellersetfiles: + 14766.patch

nosy: + greg.weller
messages: + msg160335

keywords: + patch
2012年05月10日 00:07:56r.david.murraysetkeywords: + easy

stage: needs patch
messages: + msg160317
versions: + Python 2.7, Python 3.2, Python 3.3, - Python 2.6
2012年05月09日 23:44:33Chris.Bergstressersetmessages: + msg160316
2012年05月09日 22:56:33r.david.murraysetnosy: + r.david.murray, belopolsky
messages: + msg160315
2012年05月09日 22:11:09Chris.Bergstressercreate

AltStyle によって変換されたページ (->オリジナル) /