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: Year range in timetuple
Type: behavior Stage: commit review
Components: Extension Modules Versions: Python 3.2
process
Status: closed Resolution: accepted
Dependencies: Superseder:
Assigned To: belopolsky Nosy List: belopolsky, gvanrossum, mark.dickinson
Priority: normal Keywords: patch

Created on 2010-06-16 03:57 by belopolsky, last changed 2022-04-11 14:57 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
issue9005.diff belopolsky, 2010-06-19 21:46
issue9005a.diff belopolsky, 2010-06-21 14:25 More test cases and a NEWS entry
issue9005b.diff belopolsky, 2010-06-21 14:55 Cleaned up the tests and updated the documentation.
issue9005c.diff belopolsky, 2010-07-05 15:46 Remove year <= 0 special case.
Messages (8)
msg107907 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2010-06-16 03:57
Current datetime.timetuple() implementation goes out of its way to support edge cases that produce timetuples beyond the naive datetime range:

>>> t1 = datetime.min.replace(tzinfo=timezone.max)
>>> t2 = datetime.max.replace(tzinfo=timezone.min)
>>> print(t1.utctimetuple())
time.struct_time(tm_year=0, tm_mon=12, tm_mday=31, tm_hour=0, tm_min=1, tm_sec=0, tm_wday=6, tm_yday=366, tm_isdst=0)
>>> print(t2.utctimetuple())
time.struct_time(tm_year=10000, tm_mon=1, tm_mday=1, tm_hour=23, tm_min=58, tm_sec=59, tm_wday=5, tm_yday=1, tm_isdst=0)

The last result is particularly troublesome because it may crash time.asctime on POSIX compliant systems.  See Issue #6608.

tm_year is described in help(time) as 4-digit year suggesting range of [1000, 9999].  Most C libraries support even smaller ranges.
msg108220 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2010-06-20 01:29
Note that a recently closed issue 7150 similarly tightened up datetime operations by making out of range dates raise OverflowError rather than produce non-sensible result.  This case is not a clear cut, but now with timezone.utc available in datetime module, I believe users should be encouraged to use t.astimezone(timezone.utc) to produce UTC time.  If timetuple is required the later can be converted using timetuple() method.  Idelally, t.utctimetuple() should be deprecated in favor of more explicit t.astimezone(timezone.utc).timetuple().  Unfortunately the two expressions are subtly different because 

>>> t = datetime.max.replace(tzinfo=timezone.min)
>>> t.astimezone(timezone.utc)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: date value out of range
msg108271 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2010-06-21 14:25
I raised this issue on python-dev and Guido said "OK."  See "[Python-Dev] Year 0 and year 10,000 in timetuple", http://mail.python.org/pipermail/python-dev/2010-June/100682.html

I am attaching a "commit ready" patch which contains a few more test cases and a NEWS entry.  I don't think there is a need to mention this in documentation, but at some point I would like to be able to write that dt.utctimetuple() is equivalent to dt.astimezone(timezone.utc).timetuple(), but at the moment it is not quite so.  See issue 9004.
msg108274 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2010-06-21 15:25
Committed in r82128.
msg109329 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2010-07-05 15:46
Reopening to consider removing a special case in days_before_year(..).  After r82128, year cannot be <= 0.
msg109340 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2010-07-05 17:23
Similarly, it appears that


    if (*m < 1 || *m > 12) {
	--*m;
        normalize_pair(y, m, 12);
        ++*m;
        /* |y| can't be bigger than about                                                                                                                                                
         * |original y| + |original m|/12 now.                                                                                                                                           
         */
    }

in normalize_y_m_d(int *y, int *m, int *d) is a dead branch.
msg111205 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2010-07-22 18:23
Mark,

Do you agree that conditions mentioned in msg109329 and msg109340 are never triggered?
msg118600 - (view) Author: Alexander Belopolsky (belopolsky) * (Python committer) Date: 2010-10-13 22:55
Committed in r85441.
History
Date User Action Args
2022-04-11 14:57:02adminsetgithub: 53251
2010-10-13 22:55:17belopolskysetstatus: open -> closed

messages: + msg118600
2010-07-22 18:23:21belopolskysetmessages: + msg111205
2010-07-05 17:23:48belopolskysetmessages: + msg109340
2010-07-05 15:46:40belopolskysetstatus: closed -> open
files: + issue9005c.diff
messages: + msg109329

stage: resolved -> commit review
2010-06-21 15:25:54belopolskysetstatus: open -> closed

messages: + msg108274
stage: commit review -> resolved
2010-06-21 14:55:36belopolskysetfiles: + issue9005b.diff
2010-06-21 14:25:07belopolskysetfiles: + issue9005a.diff
resolution: accepted
messages: + msg108271

stage: patch review -> commit review
2010-06-20 01:29:18belopolskysetnosy: + gvanrossum
messages: + msg108220
2010-06-19 21:46:25belopolskysetstage: needs patch -> patch review
2010-06-19 21:46:10belopolskysetfiles: + issue9005.diff
keywords: + patch
2010-06-16 03:57:06belopolskycreate