3001年1月1日は木曜日

へぇ。

例によって Python ドキュメント (What’s New)。

Several functions now have significantly expanded date ranges. When :attr:`time.accept2dyear` is false, the :func:`time.asctime` function will accept any year that fits in a C int, while the :func:`time.mktime` and :func:`time.strftime` functions will accept the full range supported by the corresponding operating system functions.

ん。これってどんだけだ、と。

これは 3.2 での説明なんだけれど、3.2 までは 2.7 も歩調合せてあるものも多く、2.7 でも一緒かもしんない。ちょっとやってみたんだけれど、なんだこれ、意味わかんない:

 1 Python 3.5.1 (v3.5.1:37a07cee5969, Dec  6 2015, 01:54:25) [MSC v.1900 64 bit (AMD64)] on win32
 2 Type "help", "copyright", "credits" or "license" for more information.
 3 >>> import time
 4 >>> time.asctime(time.localtime(2**31))
 5 'Tue Jan 19 12:14:08 2038'
 6 >>> time.asctime(time.localtime(2**32))
 7 'Sun Feb  7 15:28:16 2106'
 8 >>> time.asctime(time.localtime(2**33))
 9 'Wed Mar 16 21:56:32 2242'
10 >>> time.asctime(time.localtime(2**34))
11 'Wed May 30 10:53:04 2514'
12 >>> time.asctime(time.localtime(2**35))
13 Traceback (most recent call last):
14   File "<stdin>", line 1, in <module>
15 OSError: [Errno 22] Invalid argument
16 >>> time.asctime(time.localtime(2**35 - 2**31 + 10*365*24*60*60 + 88*24*60*60))
17 'Thu Jan  1 09:32:00 3001'
18 >>> time.asctime(time.localtime(2**35 - 2**31 + 10*365*24*60*60 + 89*24*60*60))
19 Traceback (most recent call last):
20   File "<stdin>", line 1, in <module>
21 OSError: [Errno 22] Invalid argument
22 >>> 
 1 Python 2.7.9 (default, Dec 10 2014, 12:28:03) [MSC v.1500 64 bit (AMD64)] on win32
 2 Type "help", "copyright", "credits" or "license" for more information.
 3 >>> import time
 4 >>> time.asctime(time.localtime(2**31))
 5 'Tue Jan 19 12:14:08 2038'
 6 >>> time.asctime(time.localtime(2**32))
 7 'Sun Feb 07 15:28:16 2106'
 8 >>> time.asctime(time.localtime(2**33))
 9 'Wed Mar 16 21:56:32 2242'
10 >>> time.asctime(time.localtime(2**34))
11 'Wed May 30 10:53:04 2514'
12 >>> time.asctime(time.localtime(2**35))
13 Traceback (most recent call last):
14   File "<stdin>", line 1, in <module>
15 ValueError: (22, 'Invalid argument')
16 >>> time.asctime(time.localtime(2**35 - 2**31 + 10*365*24*60*60 + 88*24*60*60))
17 'Thu Jan 01 09:32:00 3001'
18 >>> time.asctime(time.localtime(2**35 - 2**31 + 10*365*24*60*60 + 89*24*60*60))
19 Traceback (most recent call last):
20   File "<stdin>", line 1, in <module>
21 ValueError: (22, 'Invalid argument')
22 >>> 

うーん、知らなかった。

「the full range supported by the corresponding operating system functions」といっているので今の場合 MSVCRT がこの振る舞いをしていると言っているんだと思うんだけれども、なんで 3001 年 1 月 1 日なんだろか。ほかの OS でも試したら面白そうだが、まぁいいか…。(あー、なんか微かに積算マイクロ秒換算とかそんなことしてたみたいなアヤフヤな記憶があるが、そんなだっけか?)

とさらに少しやってて、読み間違えにも気付き、そしてこんな妙なことがわかった:

 1 Python 2.7.9 (default, Dec 10 2014, 12:28:03) [MSC v.1500 64 bit (AMD64)] on win32
 2 Type "help", "copyright", "credits" or "license" for more information.
 3 >>> import time
 4 >>> time.asctime((2**31, 1, 1, 9, 32, 0, 3, 1, 0))
 5 Traceback (most recent call last):
 6   File "<stdin>", line 1, in <module>
 7 OverflowError: Python int too large to convert to C long
 8 >>> time.asctime((2**30, 1, 1, 9, 32, 0, 3, 1, 0))
 9 'Thu Jan 01 09:32:00 }824'
10 >>> time.asctime((2**16, 1, 1, 9, 32, 0, 3, 1, 0))
11 'Thu Jan 01 09:32:00 q536'
12 >>> time.asctime((2**15, 1, 1, 9, 32, 0, 3, 1, 0))
13 'Thu Jan 01 09:32:00 P768'
14 >>> time.asctime((2**14, 1, 1, 9, 32, 0, 3, 1, 0))
15 'Thu Jan 01 09:32:00 @384'
16 >>> time.asctime((2**13, 1, 1, 9, 32, 0, 3, 1, 0))
17 'Thu Jan 01 09:32:00 8192'
18 >>> time.asctime((2**10, 1, 1, 9, 32, 0, 3, 1, 0))
19 Traceback (most recent call last):
20   File "<stdin>", line 1, in <module>
21 ValueError: year out of range

最後のはオマケとして(小さすぎる年)、なんだ「@384年」て。で、これらは 3.x では直っている:

 1 Python 3.5.1 (v3.5.1:37a07cee5969, Dec  6 2015, 01:54:25) [MSC v.1900 64 bit (AMD64)] on win32
 2 Type "help", "copyright", "credits" or "license" for more information.
 3 >>> import time
 4 >>> time.asctime((2**31, 1, 1, 9, 32, 0, 3, 1, 0))
 5 Traceback (most recent call last):
 6   File "<stdin>", line 1, in <module>
 7 OverflowError: Python int too large to convert to C long
 8 >>> time.asctime((2**30, 1, 1, 9, 32, 0, 3, 1, 0))
 9 'Thu Jan  1 09:32:00 1073741824'
10 >>> time.asctime((2**16, 1, 1, 9, 32, 0, 3, 1, 0))
11 'Thu Jan  1 09:32:00 65536'
12 >>> time.asctime((2**15, 1, 1, 9, 32, 0, 3, 1, 0))
13 'Thu Jan  1 09:32:00 32768'
14 >>> time.asctime((2**14, 1, 1, 9, 32, 0, 3, 1, 0))
15 'Thu Jan  1 09:32:00 16384'
16 >>> time.asctime((2**13, 1, 1, 9, 32, 0, 3, 1, 0))
17 'Thu Jan  1 09:32:00 8192'
18 >>> time.asctime((2**10, 1, 1, 9, 32, 0, 3, 1, 0))
19 'Thu Jan  1 09:32:00 1024'