time.strftime question on 0 as argument

eryk sun eryksun at gmail.com
Mon Jan 28 20:03:42 EST 2019


On 1/28/19, David Raymond <David.Raymond at tomtom.com> wrote:
>
> In the docs there is
> "0 is a legal argument for any position in the time tuple; if it is normally
> illegal the value is forced to a correct one."

The POSIX specification for strftime only states that "[i]f any of the
specified values are outside the normal range, the characters stored
are unspecified" [1]. Python tries to bring some semblance of order
across the various implementations of this function.

For tm_year, it was eventually decided circa Python 3.2 to support the
full signed range on most platforms, even if isn't a normal date, such
as year 0 and negative year values. For example, in 3.6.7 in Linux:

    >>> time.strftime("%Y = %C * 100 + %y", (0, 0, 0, 0, 0, 0, 0, 0, 0))
    '0 = 0 * 100 + 00'

    >>> time.strftime("%Y = %C * 100 + %y", (-10, 0, 0, 0, 0, 0, 0, 0, 0))
    '-10 = -1 * 100 + 90'

2.7.15 in Linux has different behavior, especially if
time.accept2dyear is true (set by default unless the environment
variable PYTHONY2K is defined).

    >>> time.accept2dyear
    1

    >>> time.strftime("%Y = %C * 100 + %y", (0, 0, 0, 0, 0, 0, 0, 0, 0))
    '2000 = 20 * 100 + 00'

    >>> time.strftime("%Y = %C * 100 + %y", (-10, 0, 0, 0, 0, 0, 0, 0, 0))
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: year out of range

The magical year value of 2000 comes from code to support pre-Y2K
scripts that assume years 69-99 are 1969-1999 and years 0-68 are
2000-2068. If we force time.accept2dyear to false, we see that Python
2 actually requires the year to be at least 1900.

    >>> time.accept2dyear = 0

    >>> time.strftime("%Y = %C * 100 + %y", (0, 0, 0, 0, 0, 0, 0, 0, 0))
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ValueError: year >= 1900 required

> and yet if given 0 for the year/first item in the tuple it raises a
> ValueError.
>
> Is that a bug in the code, the documentation, or my understanding?

It's not a bug. However, in recent versions of the Windows C runtime,
"%y" does support year values down to 0 (but not negative years), so
the check [2] can be relaxed down to 0 (whatever year 0 is supposed to
be), and the additional check for "%y" can be removed [3].

[1]: http://pubs.opengroup.org/onlinepubs/9699919799/functions/strftime.html
[2]: https://github.com/python/cpython/blob/v3.7.2/Modules/timemodule.c#L721
[3]: https://github.com/python/cpython/blob/v3.7.2/Modules/timemodule.c#L760



More information about the Python-list mailing list