Skip to main content
 首页 » 编程设计

python之将带有日期和时区的字符串解析为 UTC 日期时间

2025年05月04日18Leo_wl

我正在编写一个 Python 3 脚本,它接收带偏移量的完整日期,我希望能够将它与另一个没有偏移量的日期进行比较。我面临的主要问题是 Python 似乎不喜欢不同的偏移日期时间对象,因为当您尝试对这些对象执行任何操作时它会提示:

>>> date_string 
'Wed, 8 May 2013 15:33:29 +0200' 
>>> new_date = datetime.strptime(date_string, '%a, %d %b %Y %H:%M:%S %z') 
>>> new_date 
datetime.datetime(2013, 5, 8, 15, 33, 29, tzinfo=datetime.timezone(datetime.timedelta(0, 7200))) 
>>> new_date - datetime.today() 
Traceback (most recent call last): 
  File "<stdin>", line 1, in <module> 
TypeError: can't subtract offset-naive and offset-aware datetimes 

作为一种解决方法,我将 date_string 拆分为两个字符串,一个带有日期,一个带有偏移量,创建了两个对象:一个日期和一个增量,它们将它们相加:

>>> date_string 
'Wed, 8 May 2013 15:33:29 +0200' 
>>> match = re.match(r'(.*)(\s\+\d{4})',date_string) 
>>> match.group(1) 
'Wed, 8 May 2013 15:33:29' 
>>> match.group(2) 
' +0200' 
>>> parsed_date = datetime.strptime(match.group(1), '%a, %d %b %Y %H:%M:%S') 
>>> match_delta = re.match(r'\s\+(\d{2})(\d{2})',match.group(2)) 
>>> parsed_date_delta = timedelta(minutes=int(match_delta.group(2)),hours=int(match_delta.group(1))) 
>>> parsed_date_complete = parsed_date + parsed_date_delta 
>>> parsed_date_complete 
datetime.datetime(2013, 5, 8, 17, 33, 29) 

有了这个,我能够获得应用了正确偏移量的最后一小时,因此与另一个正常日期时间对象的任何比较都不会引发错误。

我想知道是否有更简单或更有效的方法来实现这一点。我的想法是接收这样的字符串:Wed, 8 May 2013 15:33:29 +0200 并能够将其转换为没有偏移量的日期时间对象,这样我就可以使用 UTC 时间.

编辑:为了进一步解释这个问题,new_date 的偏移值为 +0200 而 datetime.today() 和 datetime.utcnow() 没有该偏移量,因此尝试比较它或执行任何操作会在 Python 中产生以下错误:TypeError: can't subtract offset-naive and offset-aware日期时间。

如果日期是 Wed, 8 May 2013 15:33:29 +0200,我想要的是这样计算日期的方法:Wed, 8 May 2013 17:33: 29,没有偏移值但有正确的时间(偏移应用于时间)。这样,由于我没有偏移量,我可以自由地使用 datetime.today() 和 datetime.utcnow()

做一些事情

请您参考如下方法:

我不是 Python 大师,但根据 these docs :

classmethod datetime.today()

Return the current local datetime, with tzinfo None. ...

没有与返回值关联的时区。它不是在 UTC,只是未指定偏移量。因此,它不允许您比较两者是有道理的。结果将毫无意义。

换句话说,你期望这会是什么结果?

10 May 2013 13:00 +0200  >  10 May 2013 12:00 
  • 它可能是真的,因为 13:00 比 12:00 是一个更大的值。
  • 它可能是错误的,因为本地时区偏移量可能是-0100,所以您比较的时刻是11:00Z > 13:00Z。但谁知道我们是否打算使用本地偏移量,因为我们没有指定。

由于我们在左侧指的是一个精确的时刻,而在右侧指的是一个模棱两可的时刻,因此该操作会出错。

当您尝试执行此操作时,Python 会给出错误,这很好。 .Net 等其他框架做出一些假设并返回可能不是您所期望的结果。 (Read here 如果您有兴趣。)

所以回到你的问题,你说:

The idea is to receive a string like this one: Wed, 8 May 2013 15:33:29 +0200 and be able to convert it in a datetime object without offset, so I can work with UTC times.

您拥有的字符串已经反射(reflect)了它与 UTC 的偏移量。你解析它的方式很好。你只需要将它与更有意义的东西进行比较,例如 datetime.now(timezone.utc)