gh-80620: Support negative timestamps on windows in time.gmtime, time.localtime, and datetime module#143463
Conversation
datetime.datetimedatetime module
0b9b5e8 to
64c70c3
Compare
vstinner
left a comment
There was a problem hiding this comment.
I would prefer to change datetime in a separated PR, and restrict this change to time.gmtime() and time.localtime() changes.
You should document time.gmtime() and time.localtime() changes in a NEWS entry.
Python/pytime.c
Outdated
| /* Calculate day of year using Windows FILETIME difference */ | ||
| // SYSTEMTIME st_jan1 = {st_result.wYear, 1, 0, 1, 0, 0, 0, 0}; | ||
| // FILETIME ft_jan1, ft_date; | ||
| // if (!SystemTimeToFileTime(&st_jan1, &ft_jan1) || | ||
| // !SystemTimeToFileTime(&st_result, &ft_date)) { | ||
| // PyErr_SetFromWindowsErr(0); | ||
| // return -1; | ||
| // } | ||
| // ULARGE_INTEGER jan1, date; | ||
| // jan1.LowPart = ft_jan1.dwLowDateTime; | ||
| // jan1.HighPart = ft_jan1.dwHighDateTime; | ||
| // date.LowPart = ft_date.dwLowDateTime; | ||
| // date.HighPart = ft_date.dwHighDateTime; | ||
| // /* Convert 100-nanosecond intervals to days */ | ||
| // LONGLONG days_diff = (date.QuadPart - jan1.QuadPart) / (24LL * 60 * 60 * HUNDRED_NS_PER_SEC); | ||
|
|
||
| // tm->tm_yday = (int)days_diff; |
There was a problem hiding this comment.
Please remove commented/dead code.
There was a problem hiding this comment.
Do you think that yday is important to have? Doesn't impact datetime AFAIK but it does show up in struct_time objects returned from gmtime/localtime. For completeness with respect to time module it could be put back in.
There was a problem hiding this comment.
If possible, it would be better to fill tm_yday as well.
There was a problem hiding this comment.
Restored tm_yday calculation, I think the windows API version was a bit heavy so simplified it by adding custom util function.
|
test_time.test_mktime() can be updated: |
I was going to tweak callsites so it doesn't impact |
Oh, it's a good thing to implement the new feature in the Existing test_time test: def test_mktime(self):
# Issue #1726687
for t in (-2, -1, 0, 1):
try:
tt = time.localtime(t)
except (OverflowError, OSError):
pass
else:
self.assertEqual(time.mktime(tt), t)If localtime() is modified to support negative timestamp, but mktime() can still fail, the test should be modified to something like: for t in (-2, -1, 0, 1):
tt = time.localtime(t)
try:
t2 = time.mktime(tt)
except (OverflowError, OSError):
pass
else:
self.assertEqual(t2, t) |
datetime moduletime.gmtime, time.localtime, and datetime module
vstinner
left a comment
There was a problem hiding this comment.
Thanks for additional test on leap and non-leap years.
vstinner
left a comment
There was a problem hiding this comment.
LGTM. I just have minor coding style suggestions on comments.
Co-authored-by: Victor Stinner <vstinner@python.org>
|
Suggestions applied, thanks again for review! |
|
Merged, thanks. This was a long awaited feature :-) |
|
|
|
Oh, test_gmtime() fails on 32-bit systems: I wrote #143861 to fix the test. |
|
…e`, `time.localtime`, and `datetime` module (python#143463) Previously, negative timestamps (representing dates before 1970-01-01) were not supported on Windows due to platform limitations. The changes introduce a fallback implementation using the Windows FILETIME API, allowing negative timestamps to be correctly handled in both UTC and local time conversions. Additionally, related test code is updated to remove Windows-specific skips and error handling, ensuring consistent behavior across platforms. Co-authored-by: Victor Stinner <vstinner@python.org>
Previously, negative timestamps (representing dates before 1970-01-01) were not supported on Windows due to platform limitations. The changes introduce a fallback implementation using the Windows FILETIME API, allowing negative timestamps to be correctly handled in both UTC and local time conversions. Additionally, related test code is updated to remove Windows-specific skips and error handling, ensuring consistent behavior across platforms.
This may have some overlap and/or impact on the proposed changes in #134461
Other related issues:
datetime.fromtimestamp(t).astimezone()fails for0<=t<86400in Windows #107078