如何要求在 Python 验证期间将时间戳补零?
How to require a timestamp to be zero-padded during validation in Python?
我正在尝试验证一个字符串,该字符串应该包含格式为 ISO 8601 的时间戳(通常用于 JSON)。
Python 的 strptime
在验证零填充方面似乎非常宽容,请参见下面的代码示例(请注意小时缺少前导零):
>>> import datetime
>>> s = '1985-08-23T3:00:00.000'
>>> datetime.datetime.strptime(s, '%Y-%m-%dT%H:%M:%S.%f')
datetime.datetime(1985, 8, 23, 3, 0)
例如,它优雅地接受一个小时未被零填充的字符串,并且不会像我期望的那样抛出 ValueError
异常。
有什么方法可以强制 strptime 验证它是否被零填充?或者 Python 的标准库中是否还有其他内置函数?
我想避免为此编写自己的 regexp
。
要强制 strptime
为您验证前导零,您必须将自己的文字添加到 Python 的 _strptime._TimeRE_cache
。该解决方案非常 hacky,很可能不是很便携,并且需要编写 RegEx - 尽管只是时间戳的小时部分。
该问题的另一种解决方案是编写您自己的函数,该函数使用 strptime
并将解析的日期转换回字符串并比较这两个字符串。此解决方案是可移植的,但它缺乏明确的错误消息 - 您将无法区分小时、分钟、秒中缺少的前导零。
除了弄乱 Python 内部结构之外,我唯一能想到的就是通过了解您要查找的内容来测试格式的有效性。
所以,如果我猜对了,格式是 '%Y-%m-%dT%H:%M:%S.%f'
并且应该用零填充。
然后,您知道要查找的字符串的确切长度并重现预期结果..
import datetime
s = '1985-08-23T3:00:00.000'
stripped = datetime.datetime.strptime(s, '%Y-%m-%dT%H:%M:%S.%f')
try:
assert len(s) == 23
except AssertionError:
raise ValueError("time data '{}' does not match format '%Y-%m-%dT%H:%M:%S.%f".format(s))
else:
print(stripped) #just for good measure
>>ValueError: time data '1985-08-23T3:00:00.000' does not match format '%Y-%m-%dT%H:%M:%S.%f
你说你想避免使用正则表达式,但这实际上是适合使用正则表达式的问题类型。正如您所发现的,strptime
对于接受的输入非常灵活。但是,这个问题的正则表达式比较容易编写:
import re
date_pattern = re.compile(r'\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}')
s_list = [
'1985-08-23T3:00:00.000',
'1985-08-23T03:00:00.000'
]
for s in s_list:
if date_pattern.match(s):
print "%s is valid" % s
else:
print "%s is invalid" % s
输出
1985-08-23T3:00:00.000 is invalid
1985-08-23T03:00:00.000 is valid
在 repl.it
上试用
已经有一个答案,用 Python strptime() 解析 ISO8601 或 RFC3339 date/time 是不可能的:How to parse an ISO 8601-formatted date?
所以,为了回答你的问题,标准 Python 库中没有办法可靠地解析这样的日期。
关于正则表达式建议,日期字符串如
2020-14-32T45:33:44.123
将生成有效日期。有很多 Python 模块(如果您在 https://pypi.python.org 上搜索 "iso8601"),但是构建 complete ISO8601 验证器需要闰秒之类的东西、可能的时区偏移值列表等等。
我正在尝试验证一个字符串,该字符串应该包含格式为 ISO 8601 的时间戳(通常用于 JSON)。
Python 的 strptime
在验证零填充方面似乎非常宽容,请参见下面的代码示例(请注意小时缺少前导零):
>>> import datetime
>>> s = '1985-08-23T3:00:00.000'
>>> datetime.datetime.strptime(s, '%Y-%m-%dT%H:%M:%S.%f')
datetime.datetime(1985, 8, 23, 3, 0)
例如,它优雅地接受一个小时未被零填充的字符串,并且不会像我期望的那样抛出 ValueError
异常。
有什么方法可以强制 strptime 验证它是否被零填充?或者 Python 的标准库中是否还有其他内置函数?
我想避免为此编写自己的 regexp
。
要强制 strptime
为您验证前导零,您必须将自己的文字添加到 Python 的 _strptime._TimeRE_cache
。该解决方案非常 hacky,很可能不是很便携,并且需要编写 RegEx - 尽管只是时间戳的小时部分。
该问题的另一种解决方案是编写您自己的函数,该函数使用 strptime
并将解析的日期转换回字符串并比较这两个字符串。此解决方案是可移植的,但它缺乏明确的错误消息 - 您将无法区分小时、分钟、秒中缺少的前导零。
除了弄乱 Python 内部结构之外,我唯一能想到的就是通过了解您要查找的内容来测试格式的有效性。
所以,如果我猜对了,格式是 '%Y-%m-%dT%H:%M:%S.%f'
并且应该用零填充。
然后,您知道要查找的字符串的确切长度并重现预期结果..
import datetime
s = '1985-08-23T3:00:00.000'
stripped = datetime.datetime.strptime(s, '%Y-%m-%dT%H:%M:%S.%f')
try:
assert len(s) == 23
except AssertionError:
raise ValueError("time data '{}' does not match format '%Y-%m-%dT%H:%M:%S.%f".format(s))
else:
print(stripped) #just for good measure
>>ValueError: time data '1985-08-23T3:00:00.000' does not match format '%Y-%m-%dT%H:%M:%S.%f
你说你想避免使用正则表达式,但这实际上是适合使用正则表达式的问题类型。正如您所发现的,strptime
对于接受的输入非常灵活。但是,这个问题的正则表达式比较容易编写:
import re
date_pattern = re.compile(r'\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}')
s_list = [
'1985-08-23T3:00:00.000',
'1985-08-23T03:00:00.000'
]
for s in s_list:
if date_pattern.match(s):
print "%s is valid" % s
else:
print "%s is invalid" % s
输出
1985-08-23T3:00:00.000 is invalid
1985-08-23T03:00:00.000 is valid
在 repl.it
上试用已经有一个答案,用 Python strptime() 解析 ISO8601 或 RFC3339 date/time 是不可能的:How to parse an ISO 8601-formatted date? 所以,为了回答你的问题,标准 Python 库中没有办法可靠地解析这样的日期。 关于正则表达式建议,日期字符串如
2020-14-32T45:33:44.123
将生成有效日期。有很多 Python 模块(如果您在 https://pypi.python.org 上搜索 "iso8601"),但是构建 complete ISO8601 验证器需要闰秒之类的东西、可能的时区偏移值列表等等。