解析日期时,%y指令究竟是如何解释的?

时间:2018-04-20 23:27:27

标签: python date time strptime

在阅读this question关于解析表单%m/%d/%y的日期时,我意识到我不知道%y指令实际上是如何工作的。

docs说明以下内容:

  

没有世纪的年份作为零填充十进制数。

但它使用哪个世纪?如果我使用%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的正式规范?

3 个答案:

答案 0 :(得分:4)

来自time文档,强调我的:

  

2000年(Y2K)问题:Python依赖于平台的C库,它通常没有2000年问题,因为所有日期和时间都在内部表示为自纪元以来的秒数。给定strptime()格式代码时,函数%y可以解析2位数年份。 解析2位数年份时,会根据POSIX和ISO C标准进行转换:值69-99映射到1969-1999,值0-68映射到2000-2068。

答案 1 :(得分:1)

你可以阅读strptime here的CPython实现,尤其是第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中也解释了这种行为:

  

2000年(Y2K)问题:Python依赖于平台的C库,它通常没有2000年的问题,因为所有日期和时间都在内部表示为自纪元以来的秒数。函数strptime()可以在给定%y格式代码时解析2位数年份。当解析2位数年份时,它们将根据POSIX和ISO C标准进行转换:值69-99映射到1969-1999,值0-68映射到2000-2068

答案 2 :(得分:0)

strptime大概是C strptime的基本包装。

strptimethe POSIX specification states

  

%y世纪内的一年。如果没有另外说明一个世纪,则[69,99]范围内的数值应指1969年至1999年(含),[00,68]范围内的数值应指2000至2068年(含);应允许前导零,但不得要求。

     

注意:预计在IEEE Std 1003.1-2001的未来版本中,从2位数年份推断出的默认世纪将发生变化。 (这适用于接受2位数年份作为输入的所有命令。)