time module error.

Skip Montanaro skip at pobox.com
Thu Sep 13 13:20:53 EDT 2001


>>>>> "Chris" == Chris Barker <chrishbarker at home.net> writes:

    Chris> Des Small wrote:
    >> >>> t = time.strptime( '2',"%H")
    >> >>> t
    >> (1900, 1, 0, 2, 0, 0, 6, 1, 0)
    >> >>> time.mktime(t)
    >> Traceback (most recent call last):
    >> File "<stdin>", line 1, in ?
    >> OverflowError: mktime argument out of range

    >> Now, I can easily enough convert hours to seconds in my own code, but
    >> I don't understand why the above fails.

The mktime C library call which time.mktime wraps is both limited in its
range *and* platform-dependent *and* treats various ranges of years
differently.  As Chris pointed out, if you want something more robust, use
mxDateTime in the mxTools package. 

    Chris> mktime() can't handle the year 1900 or 1901, but 1902 and so on
    Chris> works.  Oddly enough, if you try to put in 1800, you get:

    >>> time.mktime((1800, 1, 1, 0, 0, 0, 3, 1, 0))
    Traceback (most recent call last):
      File "<stdin>", line 1, in ?
    ValueError: year out of range (00-99, 1900-*)

    Chris> Which implies that it should handle 1900.

Well, the error message is a bit hosed, but dates back to the time when
Python was a language being developed by Guido on Macs at CWI.  The base
epoch for Macs is/was 1904.  In 2.2 this message is made more vague in order
to be more accurate <wink>.  According to "man mktime" on my Mandrrake 8.0
system, the tm_year field of the tm structure is interpreted as

       tm_year
              The number of years since 1900.

So, you can see it is very likely not to be Y2K-compliant.  If you look in
the code for gettmarg in Modules/timemodule.c you'll see that it tries to
dance carefully around this limitation:

    if (y < 1900) {
            PyObject *accept = PyDict_GetItemString(moddict,
                                                    "accept2dyear");
            if (accept == NULL || !PyInt_Check(accept) ||
                PyInt_AsLong(accept) == 0) {
                    PyErr_SetString(PyExc_ValueError,
                                    "year >= 1900 required");
                    return 0;
            }
            if (69 <= y && y <= 99)
                    y += 1900;
            else if (0 <= y && y <= 68)
                    y += 2000;
            else {
                    PyErr_SetString(PyExc_ValueError,
                                    "year out of range");
                    return 0;
            }
    }

-- 
Skip Montanaro (skip at pobox.com)
http://www.mojam.com/
http://www.musi-cal.com/




More information about the Python-list mailing list