【问题标题】:Time data does not match format '%c'时间数据与格式“%c”不匹配
【发布时间】:2021-03-31 15:20:30
【问题描述】:

这是非常出乎意料的行为...

  1. 我使用'%c' 指令创建了一个时间字符串。

    %cLocale’s appropriate date and time representation

  2. 然后我尝试解析生成的时间字符串,指定与字符串格式相同的'%c'

  3. 但是,正如您从下面的错误中看到的那样,这不起作用。我错过了什么?

我需要能够将时间存储在人类可读的本地化字符串中,然后将该字符串转换回struct_time,以便从中提取信息。

(字符串本地化非常重要,我当然不想为世界各地的所有语言环境编写解析算法!)

# Ensure the locale is set.

import locale
locale.setlocale(locale.LC_ALL, '')
'en_US.UTF-8'

# 1. Create a localized time string using the '%c' directive.

import datetime
time_stamp = datetime.datetime.now().strftime('%c')
time_stamp
'Mon 21 Dec 2020 03:47:55 PM '

# 2. Try to parse the string using the same directive used to create it.

import time
time.strptime(time_stamp, '%c')

# 3. Unexpected error...

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.8/_strptime.py", line 562, in _strptime_time
    tt = _strptime(data_string, format)[0]
  File "/usr/lib/python3.8/_strptime.py", line 349, in _strptime
    raise ValueError("time data %r does not match format %r" %
ValueError: time data 'Mon 21 Dec 2020 03:47:55 PM ' does not match format '%c'

【问题讨论】:

  • 无法重现(在 Windows 上,Python 3.9)。 %c 对我来说是双向的,无论我是使用我的默认语言环境还是设置另一个语言环境。

标签: python datetime time datetime-format


【解决方案1】:

您可以使用 %a、%b 和其他指令指定日期格式,而不是使用 %c。例如:

import locale
locale.setlocale(locale.LC_ALL, 'en_US.utf-8')

import datetime
fmt = '%a %b %d %Y %H:%M:%S'
time_stamp = datetime.datetime.now().strftime(fmt)
print(time_stamp)

import time
print(time.strptime(time_stamp, fmt))

这会产生您正在寻找的输出:

输出:

Mon Dec 21 2020 21:27:50
time.struct_time(tm_year=2020, tm_mon=12, tm_mday=21, tm_hour=21, tm_min=27, tm_sec=50, tm_wday=0, tm_yday=356, tm_isdst=-1)

【讨论】:

  • 我更喜欢 %c,因为我负责 AM、PM、EST 之类的事情,以及不同地区的月份或日期的排序。我们是否坚持使用“硬编码”时间格式? (在您的示例中,订单被硬编码为日、月、日、年等。假设是 24 小时格式。但某些语言环境首先显示年份或使用 AM/PM)。
【解决方案2】:

您的语言环境可能没有按照您期望的方式配置.strftime("%c"),而.strptime 反对后缀%p (PM)

改用locale.nl_langinfo(locale.D_T_FMT) 构建您的格式!

>>> locale.nl_langinfo(locale.D_T_FMT)
'%a %b %e %H:%M:%S %Y'
>>> locale.setlocale(locale.LC_ALL, '')
'en_US.UTF-8'
>>> locale.nl_langinfo(locale.D_T_FMT)
'%a %b %e %X %Y'

但是,如果你

  • .. 知道输出的确切结构,用正则表达式过滤精确匹配,然后解析
  • ..可以控制格式,不用格式化直接用time.time()
  • .. 或始终以 UTC 工作并格式化为 ISO 8601,派生 tz 感知对象并使用自定义解析器回读(请参阅 the Caution on .fromisoformat
    >>> datetime.datetime.now(tz=datetime.timezone.utc)
    datetime.datetime(2020, 12, 22, 0, 4, 29, 537007, tzinfo=datetime.timezone.utc)
    
  • 使用 pytz,它比 datetime 内置库“更智能”,并且可以正确支持多种语言环境

【讨论】:

  • 我理解这个概念。您是在告诉系统提供适合区域设置的格式字符串。但是我如何使用字符串从 time_struct --> string --> 回到 time_struct 呢?我测试如下:f = locale.nl_langinfo(locale.D_T_FMT)t = time.strftime(f)。但是,time.strptime(t, f)en_US 语言环境生成'r' is a bad directive in format,为fr_FR 语言环境生成'T' is a bad directive in format。你有什么建议?
  • 这越来越奇怪:使用locale.nl_langinfo(locale.D_T_FMT)en_US 语言环境上返回'%r',它在fr_FR 语言环境上返回'%T'。但我找不到关于 '%r''%T' 指令的任何文档!
  • 我应该提到,locale.nl_langinfo(locale.D_T_FMT) 在我的系统上为美国语言环境生成 '%a %d %b %Y %r %Z'。它为 FR 语言环境生成 '%a %d %b %Y %T'。注意不寻常的%r%T?我在 Linux 上,我不明白为什么这与您的示例不完全一样。
  • @PJSingh 语言环境完全不同,可能不兼容。这类似于字符编码 - 只是存在您无法解决的细微分歧。 refuse the temptation to guess 并强制使用精确格式或要求提供语言环境。我已经用一些建议更新了我的答案。
猜你喜欢
  • 1970-01-01
  • 2021-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多