[Python-Dev] Checking input range in time.asctime and time.ctime

Alexander Belopolsky alexander.belopolsky at gmail.com
Thu Jan 6 05:48:38 CET 2011


On Wed, Jan 5, 2011 at 10:50 PM, Guido van Rossum <guido at python.org> wrote:
..
>> I propose to change that to
>>
>> if y < 1000:
>>    if accept2dyear:
>>        if 69 <= y <= 99:
>>            y += 1900
>>        elif 0 <= y <= 68:
>>            y += 2000
>>        else:
>>            raise ValueError("year out of range")
>> # call system function with tm_year = y - 1900
>
> The new logic doesn't look right, am I right that this is what you meant?
>
> if accept2dyear and 0 <= y < 100:
>  (convert to year >= 1970)
> if y < 1000:
>  raise ...
>

Not quite.  My proposed logic would not do any range checking if
accept2dyear == 0.

> But what guarantees do we have that the system functions accept
> negative values for tm_year on all relevant platforms?
>

I've already committed an implementation of asctime, so time.asctime
and time.ctime don't call system functions anymore.  This leaves
time.mktime and time.strftime. The latter caused Tim Peters to limit
year range to >= 1900 eight years ago:

http://svn.python.org/view?view=rev&revision=30224

For these functions, range checks are necessary only when system
functions may crash on out of range values.  If we can detect error
return and convert it to an exception, there is no need to look before
you leap. (Note that asctime was different because the relevant
standards specifically allowed it to have undefined behavior for out
of range values.)

I cannot rule out that there are systems out there with buggy
strftime, but the situation has improved in the last eight years and
we have buildbots and unittests to check behavior on relevant
platforms.  If we do find a platform with buggy strftime which crashes
or produces nonsense with negative tm_year, we can add a platform
specific range check to work around platform bug, or just ask users to
bug their OS vendor. :-)

> The 1000 limit still seems pretty arbitrary to me -- if it's only
> because you don't want to decide whether to use leading spaces or
> zeros for numbers shorter than 4 digits, let me propose leading zeros
> since we use those uniformly for months, days, hours, minutes and
> seconds < 10,

Except we don't:

>>> time.asctime((2000, 1, 1, 0, 0, 0, 0, 0, -1))
'Sat Jan  1 00:00:00 2000'

(note that day is space-filled.)

I am not sure, however, what you are proposing here.  Are you arguing
for a wider or a narrower year range? I would be happy with just

   if accept2dyear:
       if 69 <= y <= 99:
           y += 1900
       elif 0 <= y <= 68:
           y += 2000
   # call system function with tm_year = y - 1900

but I thought that would be too radical.


More information about the Python-Dev mailing list