如何在 Python 中创建时区感知日期时间对象? [英] How to make a timezone aware datetime object in Python?

查看:70
本文介绍了如何在 Python 中创建时区感知日期时间对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要做什么

我有一个不支持时区的日期时间对象,我需要向其中添加一个时区,以便能够将其与其他支持时区的日期时间对象进行比较.对于这个遗留案例,我不想将我的整个应用程序转换为时区.

我的尝试

首先演示一下问题:

Python 2.6.1(r261:67515,2010 年 6 月 24 日,21:47:49)[GCC 4.2.1 (Apple Inc. build 5646)] 在达尔文上输入帮助"、版权"、信用"或许可"以获取更多信息.>>>导入日期时间>>>进口pytz>>>不知道 = datetime.datetime(2011,8,15,8,15,12,0)>>>不知道datetime.datetime(2011, 8, 15, 8, 15, 12)>>>意识到 = datetime.datetime(2011,8,15,8,15,12,0,pytz.UTC)>>>知道的datetime.datetime(2011, 8, 15, 8, 15, 12, tzinfo=<UTC>)>>>知道 == 不知道回溯(最近一次调用最后一次):文件<stdin>",第 1 行,在 <module> 中类型错误:无法比较偏移天真和偏移感知日期时间

首先,我尝试了 astimezone:

<预><代码>>>>不知道.astimezone(pytz.UTC)回溯(最近一次调用最后一次):文件<stdin>",第 1 行,在 <module> 中ValueError: astimezone() 不能应用于简单的日期时间>>>

失败并不奇怪,因为它实际上是在尝试进行转换.替换似乎是一个更好的选择(根据 Python:如何获取时区感知"的 datetime.today() 值?):

<预><代码>>>>unaware.replace(tzinfo=pytz.UTC)datetime.datetime(2011, 8, 15, 8, 15, 12, tzinfo=<UTC>)>>>不知道 == 知道回溯(最近一次调用最后一次):文件<stdin>",第 1 行,在 <module> 中类型错误:无法比较偏移天真和偏移感知日期时间>>>

但是正如你所看到的,replace 似乎设置了 tzinfo,但没有让对象知道.我准备回退到在解析输入字符串之前修改输入字符串以获得时区(我正在使用 dateutil 进行解析,如果这很重要),但这似乎非常笨拙.

另外,我在 python 2.6 和 python 2.7 中都尝试过,结果相同.

背景

我正在为一些数据文件编写解析器.我需要支持一种旧格式,其中日期字符串没有时区指示器.我已经修复了数据源,但我仍然需要支持旧数据格式.出于各种商业 BS 原因,不能选择一次性转换遗留数据.虽然总的来说,我不喜欢硬编码默认时区的想法,但在这种情况下,它似乎是最好的选择.我有合理的信心知道所有有问题的遗留数据都是 UTC 格式的,所以我准备接受在这种情况下默认使用的风险.

解决方案

一般来说,要使日期时间感知时区,请使用 本地化方法:

导入日期时间进口pytz不知道 = datetime.datetime(2011, 8, 15, 8, 15, 12, 0)意识到 = datetime.datetime(2011, 8, 15, 8, 15, 12, 0, pytz.UTC)now_aware = pytz.utc.localize(不知道)断言意识到== now_aware

对于 UTC 时区,实际上没有必要使用 localize,因为没有要处理的夏令时计算:

now_aware = unaware.replace(tzinfo=pytz.UTC)

有效.(.replace 返回一个新的日期时间;它不会修改 unaware.)

What I need to do

I have a timezone-unaware datetime object, to which I need to add a time zone in order to be able to compare it with other timezone-aware datetime objects. I do not want to convert my entire application to timezone unaware for this one legacy case.

What I've Tried

First, to demonstrate the problem:

Python 2.6.1 (r261:67515, Jun 24 2010, 21:47:49) 
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import datetime
>>> import pytz
>>> unaware = datetime.datetime(2011,8,15,8,15,12,0)
>>> unaware
datetime.datetime(2011, 8, 15, 8, 15, 12)
>>> aware = datetime.datetime(2011,8,15,8,15,12,0,pytz.UTC)
>>> aware
datetime.datetime(2011, 8, 15, 8, 15, 12, tzinfo=<UTC>)
>>> aware == unaware
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't compare offset-naive and offset-aware datetimes

First, I tried astimezone:

>>> unaware.astimezone(pytz.UTC)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: astimezone() cannot be applied to a naive datetime
>>>

It's not terribly surprising this failed, since it's actually trying to do a conversion. Replace seemed like a better choice (as per Python: How to get a value of datetime.today() that is "timezone aware"?):

>>> unaware.replace(tzinfo=pytz.UTC)
datetime.datetime(2011, 8, 15, 8, 15, 12, tzinfo=<UTC>)
>>> unaware == aware
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't compare offset-naive and offset-aware datetimes
>>> 

But as you can see, replace seems to set the tzinfo, but not make the object aware. I'm getting ready to fall back to doctoring the input string to have a timezone before parsing it (I'm using dateutil for parsing, if that matters), but that seems incredibly kludgy.

Also, I've tried this in both python 2.6 and python 2.7, with the same results.

Context

I am writing a parser for some data files. There is an old format I need to support where the date string does not have a timezone indicator. I've already fixed the data source, but I still need to support the legacy data format. A one time conversion of the legacy data is not an option for various business BS reasons. While in general, I do not like the idea of hard-coding a default timezone, in this case it seems like the best option. I know with reasonable confidence that all the legacy data in question is in UTC, so I'm prepared to accept the risk of defaulting to that in this case.

解决方案

In general, to make a naive datetime timezone-aware, use the localize method:

import datetime
import pytz

unaware = datetime.datetime(2011, 8, 15, 8, 15, 12, 0)
aware = datetime.datetime(2011, 8, 15, 8, 15, 12, 0, pytz.UTC)

now_aware = pytz.utc.localize(unaware)
assert aware == now_aware

For the UTC timezone, it is not really necessary to use localize since there is no daylight savings time calculation to handle:

now_aware = unaware.replace(tzinfo=pytz.UTC)

works. (.replace returns a new datetime; it does not modify unaware.)

这篇关于如何在 Python 中创建时区感知日期时间对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆