解析日期时 %y 指令究竟是如何解释的?
How exactly is the %y directive interpreted when parsing dates?
在阅读 关于解析 %m/%d/%y
形式的日期时,我意识到我不知道 %y
指令的实际工作原理。
docs 声明如下:
Year without century as a zero-padded decimal number.
但是它使用的是哪个世纪?如果我使用 %y
来解析年份 01
,结果是 1901 年还是 2001 年?如果我在 100 年后重新 运行 相同的代码,结果会是 2101 吗?
作为实验,我编写了一些代码来解析从 0 到 99 的所有数字并显示结果:
for year in range(100):
date = '6/1/{:>02}'.format(year)
dt = datetime.strptime(date, "%m/%d/%y")
print(year, dt.date())
结果令人惊讶:
0 2000-06-01
1 2001-06-01
2 2002-06-01
...
67 2067-06-01
68 2068-06-01
69 1969-06-01 # <- wut
70 1970-06-01
71 1971-06-01
...
98 1998-06-01
99 1999-06-01
为什么突然从2068跳到1969?这种行为是否记录在任何地方? %y
的正式规范是什么?
来自 time
文档,强调我的:
Year 2000 (Y2K) issues: Python depends on the platform’s C library, which generally doesn’t have year 2000 issues, since all dates and times are represented internally as seconds since the epoch. Function strptime()
can parse 2-digit years when given %y
format code. When 2-digit years are parsed, they are converted according to the POSIX and ISO C standards: values 69–99 are mapped to 1969–1999, and values 0–68 are mapped to 2000–2068.
strptime
大概是 C 的 strptime
.
的基本包装
共strptime
、the POSIX specification states:
%y
The year within century. When a century is not otherwise specified, values in the range [69,99] shall refer to years 1969 to 1999 inclusive, and values in the range [00,68] shall refer to years 2000 to 2068 inclusive; leading zeros shall be permitted but shall not be required.
Note: It is expected that in a future version of IEEE Std 1003.1-2001 the default century inferred from a 2-digit year will change. (This would apply to all commands accepting a 2-digit year as input.)
您可以阅读 strptime 的 CPython 实现 here, and in particular at lines 384-392 有一点很有趣:
if group_key == 'y':
year = int(found_dict['y'])
# Open Group specification for strptime() states that a %y
#value in the range of [00, 68] is in the century 2000, while
#[69,99] is in the century 1900
if year <= 68:
year += 2000
else:
year += 1900
手册中也解释了此行为 ot time:
Year 2000 (Y2K) issues: Python depends on the platform’s C library, which generally doesn’t have year 2000 issues, since all dates and times are represented internally as seconds since the epoch. Function strptime() can parse 2-digit years when given %y format code. When 2-digit years are parsed, they are converted according to the POSIX and ISO C standards: values 69–99 are mapped to 1969–1999, and values 0–68 are mapped to 2000–2068.
在阅读 %m/%d/%y
形式的日期时,我意识到我不知道 %y
指令的实际工作原理。
docs 声明如下:
Year without century as a zero-padded decimal number.
但是它使用的是哪个世纪?如果我使用 %y
来解析年份 01
,结果是 1901 年还是 2001 年?如果我在 100 年后重新 运行 相同的代码,结果会是 2101 吗?
作为实验,我编写了一些代码来解析从 0 到 99 的所有数字并显示结果:
for year in range(100):
date = '6/1/{:>02}'.format(year)
dt = datetime.strptime(date, "%m/%d/%y")
print(year, dt.date())
结果令人惊讶:
0 2000-06-01
1 2001-06-01
2 2002-06-01
...
67 2067-06-01
68 2068-06-01
69 1969-06-01 # <- wut
70 1970-06-01
71 1971-06-01
...
98 1998-06-01
99 1999-06-01
为什么突然从2068跳到1969?这种行为是否记录在任何地方? %y
的正式规范是什么?
来自 time
文档,强调我的:
Year 2000 (Y2K) issues: Python depends on the platform’s C library, which generally doesn’t have year 2000 issues, since all dates and times are represented internally as seconds since the epoch. Function
strptime()
can parse 2-digit years when given%y
format code. When 2-digit years are parsed, they are converted according to the POSIX and ISO C standards: values 69–99 are mapped to 1969–1999, and values 0–68 are mapped to 2000–2068.
strptime
大概是 C 的 strptime
.
共strptime
、the POSIX specification states:
%y
The year within century. When a century is not otherwise specified, values in the range [69,99] shall refer to years 1969 to 1999 inclusive, and values in the range [00,68] shall refer to years 2000 to 2068 inclusive; leading zeros shall be permitted but shall not be required.Note: It is expected that in a future version of IEEE Std 1003.1-2001 the default century inferred from a 2-digit year will change. (This would apply to all commands accepting a 2-digit year as input.)
您可以阅读 strptime 的 CPython 实现 here, and in particular at lines 384-392 有一点很有趣:
if group_key == 'y':
year = int(found_dict['y'])
# Open Group specification for strptime() states that a %y
#value in the range of [00, 68] is in the century 2000, while
#[69,99] is in the century 1900
if year <= 68:
year += 2000
else:
year += 1900
手册中也解释了此行为 ot time:
Year 2000 (Y2K) issues: Python depends on the platform’s C library, which generally doesn’t have year 2000 issues, since all dates and times are represented internally as seconds since the epoch. Function strptime() can parse 2-digit years when given %y format code. When 2-digit years are parsed, they are converted according to the POSIX and ISO C standards: values 69–99 are mapped to 1969–1999, and values 0–68 are mapped to 2000–2068.