datetime 解析年月月的逻辑是什么?
What is the logic of parsing datetime with years and months?
我不确定为什么当带有“%Y%m”的“200013”失败而带有“%Y”的“200011”时,“200011”以“%Y%m”作为格式解析为 2000-11-01 %m%d' 成功。见代码:
>>> datetime.datetime.strptime('200013', '%Y%m')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File ".../lib/python3.5/_strptime.py", line 510, in _strptime_datetime
tt, fraction = _strptime(data_string, format)
File ".../lib/python3.5/_strptime.py", line 346, in _strptime
data_string[found.end():])
ValueError: unconverted data remains: 3
>>> datetime.datetime.strptime('200011', '%Y%m')
datetime.datetime(2000, 11, 1, 0, 0)
>>> datetime.datetime.strptime('200011', '%Y%m%d')
datetime.datetime(2000, 1, 1, 0, 0)
有什么想法吗?
整数13没有对应的月份,所以在1
被解析为月份后,你必须添加一个说明符来解析3
:
>>> datetime.datetime.strptime('200013', '%Y%m%d')
datetime.datetime(2000, 1, 3, 0, 0)
'200011'
有效是因为 11
对应于 11 月,可以安全地解析为一个月,而未指定日期时默认为 1。
示例:
缺少月份、日期、小时和分钟,因此将这些设置为默认值:
datetime.datetime.strptime('2000', '%Y')
datetime.datetime(2000, 1, 1, 0, 0)
月、小时和分钟设置为默认值:
datetime.datetime.strptime('200012', '%Y%d')
datetime.datetime(2000, 1, 12, 0, 0)
在您的示例中,它正在寻找月份作为第二个参数,但没有“13”月份 - datetime.datetime.strptime('200013', '%Y%m')
但是当你说 datetime.datetime.strptime('200013', '%Y%m%d') 时,它会查找年份:2000 年,月份,因为 13 无效,它需要 1 作为月和 3 作为天
最后,在本例中:datetime.datetime.strptime('200011', '%Y%m'),查找年份,2000有效年份,查找月份,11为有效月份。现在 rest 设置为默认值(就像我在最上面给出的示例一样)。
注意以下命令,默认月份并将 13 作为有效日期。
datetime.datetime.strptime('200013', '%Y%d')
datetime.datetime(2000, 1, 13, 0, 0)
TL;DR:Python 文档忽略提及 零填充月份是可选的 。
>>> from datetime import datetime
>>> pattern = '%Y%m'
>>> datetime.strptime('20161', pattern).strftime(pattern)
'201601' # Note an extra "0" has appeared
strptime
和 strftime
的时间格式来自 C 标准库。 Python 文档在这里缺少一些重要的细节,Python 文档中的 relevant section 只是说:
%m Month as a zero-padded decimal number.
不过也提到了
The full set of format codes supported varies across platforms, because Python calls the platform C library’s strftime() function, and platform variations are common.
在此处导致令人惊讶的结果的行为,即前导零的处理,在 C 中有更好的记录:
%Y
The full year {4}; leading zeros shall be permitted but shall not be required. A leading '+' or '-' character shall be permitted before any leading zeros but shall not be required.
%m
The month number [01,12]; leading zeros shall be permitted but shall not be required.
%d
The day of the month [01,31]; leading zeros shall be permitted but shall not be required.
强调我的。来源 here。
因此,在知道可能存在或不存在前导零的情况下,所有提到的情况都已正确说明:
datetime.strptime('200013', '%Y%m') # Can not parse
由于 13 不是一个有效的月份,解析被强制取 1 是省略前导零的月份。然后你得到 ValueError
因为解析器不知道如何处理额外的数据“3”。
datetime.datetime.strptime('200011', '%Y%m') # Parses to 1st Nov
解析器以十一月 (11) 为月份。 Day 只是默认为 1。这里不可能将 1 月作为月份,因为这会使额外的数据在这种模式下无法解释 - 会有额外的尾随“1”剩余。因此,解析器必须是贪婪的,并且当月消耗'11'。
datetime.datetime.strptime('200011', '%Y%m%d') # Parses to 1st Jan
这里我们看到 '200011' 可以被 模式 %Y%m
和 %Y%m%d
成功解析。如果您使用 %Y%m%d
模式进行解析,那么您将被迫将月份作为 January (1),否则就没有剩余数据可以填充 %d
。请注意,前导零对于 %d
也是可选的。
我不确定为什么当带有“%Y%m”的“200013”失败而带有“%Y”的“200011”时,“200011”以“%Y%m”作为格式解析为 2000-11-01 %m%d' 成功。见代码:
>>> datetime.datetime.strptime('200013', '%Y%m')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File ".../lib/python3.5/_strptime.py", line 510, in _strptime_datetime
tt, fraction = _strptime(data_string, format)
File ".../lib/python3.5/_strptime.py", line 346, in _strptime
data_string[found.end():])
ValueError: unconverted data remains: 3
>>> datetime.datetime.strptime('200011', '%Y%m')
datetime.datetime(2000, 11, 1, 0, 0)
>>> datetime.datetime.strptime('200011', '%Y%m%d')
datetime.datetime(2000, 1, 1, 0, 0)
有什么想法吗?
整数13没有对应的月份,所以在1
被解析为月份后,你必须添加一个说明符来解析3
:
>>> datetime.datetime.strptime('200013', '%Y%m%d')
datetime.datetime(2000, 1, 3, 0, 0)
'200011'
有效是因为 11
对应于 11 月,可以安全地解析为一个月,而未指定日期时默认为 1。
示例: 缺少月份、日期、小时和分钟,因此将这些设置为默认值:
datetime.datetime.strptime('2000', '%Y') datetime.datetime(2000, 1, 1, 0, 0)
月、小时和分钟设置为默认值:
datetime.datetime.strptime('200012', '%Y%d') datetime.datetime(2000, 1, 12, 0, 0)
在您的示例中,它正在寻找月份作为第二个参数,但没有“13”月份 - datetime.datetime.strptime('200013', '%Y%m')
但是当你说 datetime.datetime.strptime('200013', '%Y%m%d') 时,它会查找年份:2000 年,月份,因为 13 无效,它需要 1 作为月和 3 作为天
最后,在本例中:datetime.datetime.strptime('200011', '%Y%m'),查找年份,2000有效年份,查找月份,11为有效月份。现在 rest 设置为默认值(就像我在最上面给出的示例一样)。
注意以下命令,默认月份并将 13 作为有效日期。
datetime.datetime.strptime('200013', '%Y%d') datetime.datetime(2000, 1, 13, 0, 0)
TL;DR:Python 文档忽略提及 零填充月份是可选的 。
>>> from datetime import datetime
>>> pattern = '%Y%m'
>>> datetime.strptime('20161', pattern).strftime(pattern)
'201601' # Note an extra "0" has appeared
strptime
和 strftime
的时间格式来自 C 标准库。 Python 文档在这里缺少一些重要的细节,Python 文档中的 relevant section 只是说:
%m Month as a zero-padded decimal number.
不过也提到了
The full set of format codes supported varies across platforms, because Python calls the platform C library’s strftime() function, and platform variations are common.
在此处导致令人惊讶的结果的行为,即前导零的处理,在 C 中有更好的记录:
%Y The full year {4}; leading zeros shall be permitted but shall not be required. A leading '+' or '-' character shall be permitted before any leading zeros but shall not be required.
%m The month number [01,12]; leading zeros shall be permitted but shall not be required.
%d The day of the month [01,31]; leading zeros shall be permitted but shall not be required.
强调我的。来源 here。
因此,在知道可能存在或不存在前导零的情况下,所有提到的情况都已正确说明:
datetime.strptime('200013', '%Y%m') # Can not parse
由于 13 不是一个有效的月份,解析被强制取 1 是省略前导零的月份。然后你得到 ValueError
因为解析器不知道如何处理额外的数据“3”。
datetime.datetime.strptime('200011', '%Y%m') # Parses to 1st Nov
解析器以十一月 (11) 为月份。 Day 只是默认为 1。这里不可能将 1 月作为月份,因为这会使额外的数据在这种模式下无法解释 - 会有额外的尾随“1”剩余。因此,解析器必须是贪婪的,并且当月消耗'11'。
datetime.datetime.strptime('200011', '%Y%m%d') # Parses to 1st Jan
这里我们看到 '200011' 可以被 模式 %Y%m
和 %Y%m%d
成功解析。如果您使用 %Y%m%d
模式进行解析,那么您将被迫将月份作为 January (1),否则就没有剩余数据可以填充 %d
。请注意,前导零对于 %d
也是可选的。