Issue1726687
Created on 2007-05-28 02:27 by blais, last changed 2009-03-20 15:20 by haypo.
|
msg52686 - (view) |
Author: Martin Blais (blais) |
Date: 2007-05-28 02:27 |
|
There is a bug in datetime.fromtimestamp(), whereby if it is called with -1, it fails with "mktime argument out of range" when it should not (see attached test program to reproduce the problem).
The bug is that the way that mktime() signals an error code is subtle and error-prone: you need to set a sentinel in the tm's wday or yday and not only check the return value of mktime, but also check if those values have been modified; it figures: -1 is a valid value in the return domain of mktime() and is not a sufficient condition for signaling an error.
Here is the relevant excerpt from the Linux man page:
The mktime() function converts a broken-down time structure, expressed
as local time, to calendar time representation. The function ignores
the specified contents of the structure members tm_wday and tm_yday and
recomputes them from the other information in the broken-down time
structure. If structure members are outside their legal interval, they
will be normalized (so that, e.g., 40 October is changed into 9 Novem-
ber). Calling mktime() also sets the external variable tzname with
information about the current time zone. If the specified broken-down
time cannot be represented as calendar time (seconds since the epoch),
mktime() returns a value of (time_t)(-1) and does not alter the tm_wday
and tm_yday members of the broken-down time structure.
This was found under Linux, I do not know if this bug also occurs on Windows or the Mac.
I attached a couple of files:
- timebug.py: reproduce the bug
- timebug.c: tests that mktime()'s behaviour is as wicked as expected
- timebug.patch: the fix to the datetime module.
P.S. I hit this bug in a graphics application while zooming in/out of a viewer rendering time-based data. Sheer luck.
|
|
msg52687 - (view) |
Author: Martin Blais (blais) |
Date: 2007-05-28 02:28 |
|
File Added: timebug.py
|
|
msg52688 - (view) |
Author: Martin Blais (blais) |
Date: 2007-05-28 02:29 |
|
File Added: timebug.c
|
|
msg52689 - (view) |
Author: Martin Blais (blais) |
Date: 2007-05-28 02:30 |
|
File Added: timebug.patch
|
|
msg52690 - (view) |
Author: Martin Blais (blais) |
Date: 2007-05-28 02:38 |
|
(Additional note: this bug was found and fixed with Peter Wang from Enthought.)
|
|
msg52691 - (view) |
Author: Martin v. Löwis (loewis) |
Date: 2007-05-29 05:09 |
|
Reclassifying as a patch.
|
|
msg75728 - (view) |
Author: STINNER Victor (haypo) |
Date: 2008-11-11 04:06 |
|
The patch is correct. I tried to use errno, but errno is unchanged on
error. Here is a new patch with regression tests.
|
|
msg75901 - (view) |
Author: STINNER Victor (haypo) |
Date: 2008-11-15 00:43 |
|
Can anyone review the last patch?
|
|
msg75918 - (view) |
Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) |
Date: 2008-11-15 22:33 |
|
on Windows (with Visual Studio), mktime() also sets tm_wday only if
successful.
But negative time_t are still not allowed by the Microsoft CRT, the
tests fail.
There are workaround to this - for example python could use techniques
similar to http://robertinventor.com/software/t64/
OTOH, the docs of the time module explicitly says that dates before the
Epoch are not handled. Do you want to change this? in other words: is
this a bug or a feature request?
http://docs.python.org/library/time.html
|
|
msg80797 - (view) |
Author: STINNER Victor (haypo) |
Date: 2009-01-29 23:48 |
|
> But negative time_t are still not allowed by the Microsoft CRT,
> the tests fail.
> (...)
> is this a bug or a feature request?
Linux mktime() supports any timestamp from 1901..2038. Should we limit
the timestamp to 1970 just because of Microsoft? Test tm_wday fixes a
bug on Linux and doesn't change the behaviour on Windows. So the
problem is just the unit test: the test should be different on Windows
(make sure that -1 raises an error).
|
|
msg80799 - (view) |
Author: STINNER Victor (haypo) |
Date: 2009-01-30 00:05 |
|
My test included in mktime_fix_and_tests.patch has a problem: the
timezone is constant and it's mine (GMT+1). I don't know how to write
a generic test working on any time zone. I can't use
datetime.fromtimestamp() because datetime.fromtimestamp() uses
time.mktime() :-)
|
|
msg83838 - (view) |
Author: STINNER Victor (haypo) |
Date: 2009-03-20 01:02 |
|
New version of my fix:
- the test doesn't depend on _my_ local anymore: it uses localtime()
to get the time tuple in the host local
- ignore the test if mktime(-2) raise an OverflowError: avoid the
test on Windows
Is it now ok for everyone?
|
|
msg83863 - (view) |
Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) |
Date: 2009-03-20 14:38 |
|
Is the "break" intended in the test function? it seems that this will
skip the whole test. Isn't "continue" better?
|
|
msg83864 - (view) |
Author: STINNER Victor (haypo) |
Date: 2009-03-20 15:20 |
|
@Amaury: You wrote:
<< But negative time_t are still not allowed by the Microsoft CRT,
the tests fail.>>
So I choosed to skip mktime(-1) test if mktime(-2) fails.
I don't have Windows to test my patch nor current behaviour.
|
|
| Date |
User |
Action |
Args |
| 2009-03-20 15:20:31 | haypo | set | messages:
+ msg83864 |
| 2009-03-20 14:38:22 | amaury.forgeotdarc | set | messages:
+ msg83863 |
| 2009-03-20 01:02:24 | haypo | set | files:
+ fix_mktime-2.patch
messages:
+ msg83838 |
| 2009-01-30 00:05:28 | haypo | set | messages:
+ msg80799 |
| 2009-01-29 23:48:38 | haypo | set | messages:
+ msg80797 |
| 2008-11-15 22:33:47 | amaury.forgeotdarc | set | nosy:
+ amaury.forgeotdarc messages:
+ msg75918 |
| 2008-11-15 00:43:55 | haypo | set | keywords:
+ needs review messages:
+ msg75901 stage: patch review |
| 2008-11-11 04:07:00 | haypo | set | files:
+ mktime_fix_and_tests.patch nosy:
+ haypo messages:
+ msg75728 versions:
+ Python 3.1, Python 2.7 |
| 2007-05-28 02:27:51 | blais | create | |
|