python 带有可选位的 strptime 格式

python strptime format with optional bits

现在我有:

timestamp = datetime.strptime(date_string, '%Y-%m-%d %H:%M:%S.%f')

这很好用,除非我转换的字符串没有微秒。我如何指定微秒是可选的(如果它们不在字符串中则应被视为 0)?

您可以使用 try/except 块:

try:
    timestamp = datetime.strptime(date_string, '%Y-%m-%d %H:%M:%S.%f')
except ValueError:
    timestamp = datetime.strptime(date_string, '%Y-%m-%d %H:%M:%S')

如果它不存在就追加它怎么样?

if '.' not in date_string:
    date_string = date_string + '.0'

timestamp = datetime.strptime(date_string, '%Y-%m-%d %H:%M:%S.%f')

我更喜欢使用正则表达式匹配而不是尝试和排除。这允许许多可接受格式的回退。

# full timestamp with milliseconds
match = re.match(r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+Z", date_string)
if match:
    return datetime.strptime(date_string, "%Y-%m-%dT%H:%M:%S.%fZ")

# timestamp missing milliseconds
match = re.match(r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z", date_string)
if match:
    return datetime.strptime(date_string, "%Y-%m-%dT%H:%M:%SZ")

# timestamp missing milliseconds & seconds
match = re.match(r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}Z", date_string)
if match:
    return datetime.strptime(date_string, "%Y-%m-%dT%H:%MZ")

# unknown timestamp format
return false

不要忘记为该方法导入 "re" 和 "datetime"。

datetime(*map(int, re.findall('\d+', date_string)))

可以解析'%Y-%m-%d %H:%M:%S.%f''%Y-%m-%d %H:%M:%S'。如果您的输入没有被过滤,那就太宽容了。

它快速而肮脏,但有时 strptime() 太慢了。如果您知道输入具有预期的日期格式,则可以使用它。

对于我使用 jq 的类似问题,我使用了以下内容:

|split("Z")[0]|split(".")[0]|strptime("%Y-%m-%dT%H:%M:%S")|mktime

作为按时间正确排序列表的解决方案。

使用一个正则表达式和一些列表表达式

time_str = "12:34.567"
# time format is [HH:]MM:SS[.FFF]
sum([a*b for a,b in zip(map(lambda x: int(x) if x else 0, re.match(r"(?:(\d{2}):)?(\d{2}):(\d{2})(?:\.(\d{3}))?", time_str).groups()), [3600, 60, 1, 1/1000])])
# result = 754.567

我来晚了,但我发现如果您不关心可选位,这将为您去掉 .%f。

datestring.split('.')[0]

如果您使用的是 Pandas,您还可以过滤系列并将其连接起来。索引自动加入。

import pandas as pd

# Every other row has a different format
df = pd.DataFrame({"datetime_string": ["21-06-08 14:36:09", "21-06-08 14:36:09.50", "21-06-08 14:36:10", "21-06-08 14:36:10.50"]})
df["datetime"] = pd.concat([
    pd.to_datetime(df["datetime_string"].iloc[1::2], format="%y-%m-%d %H:%M:%S.%f"),
    pd.to_datetime(df["datetime_string"].iloc[::2], format="%y-%m-%d %H:%M:%S"),
])

datetime_string datetime
0 21-06-08 14:36:09 2021-06-08 14:36:09
1 21-06-08 14:36:09.50 2021-06-08 14:36:09.500000
2 21-06-08 14:36:10 2021-06-08 14:36:10
3 21-06-08 14:36:10.50 2021-06-08 14:36:10.500000