如何在python中使不知道的datetime时区感知

How to make an unaware datetime timezone aware in python

我需要做的是

我有一个TimeZone Unknowled DateTime对象,我需要在其中添加一个时区,以便能够将其与其他TimeZone-Aknowled DateTime对象进行比较。我不想将我的整个应用程序转换为不知道这个遗留案例的时区。

我试过什么

首先,要演示问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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

首先,我尝试了Astimezone:

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

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

1
2
3
4
5
6
7
>>> 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
>>>

但正如您所看到的,replace似乎设置了TZINFO,但并没有使对象意识到。我准备在分析输入字符串之前修改它,使其具有时区(如果这很重要的话,我使用dateutil进行分析),但这看起来非常笨拙。

另外,我在python 2.6和python 2.7中都尝试过这种方法,得到了相同的结果。

语境

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


在一般的天真,让感知使用DateTime时区:localize method,theP></

1
2
3
4
5
6
7
8
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时区is not necessary to,它真的不使用localizesince there is to handle:白天时间计算储蓄P></

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

工厂。(.replace归来在unawaredoes not modify datetime;en)。P></


所有这些所谓的外部使用一模一样,但结果是你可以使用as the datetime模块也只是给我,这个答案:P></

1
2
3
4
5
6
7
8
from datetime import datetime
from datetime import timezone

dt = datetime.now()
dt.replace(tzinfo=timezone.utc)

print(dt.replace(tzinfo=timezone.utc).isoformat())
'2017-01-12T22:11:31+00:00'

不pytz fewer限制和问题。P></

注意:如果你使用this with python3愿望和python2,你可以使用this as for the进出口井的时区(UTC):硬编码)P></

1
2
3
4
5
6
7
8
9
10
11
12
13
try:
    from datetime import timezone
    utc = timezone.utc
except ImportError:
    #Hi there python2 user
    class UTC(tzinfo):
        def utcoffset(self, dt):
            return timedelta(0)
        def tzname(self, dt):
            return"UTC"
        def dst(self, dt):
            return timedelta(0)
    utc = UTC()


我使用_ DT DT从感知到_ toP></

1
dt_unaware = dt_aware.replace(tzinfo=None)

和感知到的_ _ DT DTP></

1
2
3
from pytz import timezone
localtz = timezone('Europe/Lisbon')
dt_aware = localtz.localize(dt_unware)

but is also a答案之前良好的解决方案。P></


在使用Django的this statement to convert to安安unaware感知时间:P></

1
2
3
from django.utils import timezone

dt_aware = timezone.make_aware(dt_unaware, timezone.get_current_timezone())


结果同意与以前的答案是,如果你是好的结束和开始在UTC。但我也认为它是普通人在换工作情景感知价值与TZ that has a that has a local DateTime不是UTC时区。P></

如果你是去到一个名字,可能会infer replace()will be the right和感知产生适用的DateTime对象。this is not the房屋。P></

(tzinfo=replace the…)在ITS的行为似乎是随机的。它是therefore useless。我不使用这个!P></

localize is the correct函数的使用。实例:P></

1
localdatetime_aware = tz.localize(datetime_nonaware)

或更多的完整的实例:P></

1
2
3
import pytz
from datetime import datetime
pytz.timezone('Australia/Melbourne').localize(datetime.now())

给我感知的DateTime值时区当地时间:of the currentP></

1
datetime.datetime(2017, 11, 3, 7, 44, 51, 908574, tzinfo=<DstTzInfo 'Australia/Melbourne' AEDT+11:00:00 DST>)


这codifies @ @ unutbu'塞尔吉奥和S的答案。它将与"只是工作"或者pytz.timezone或安在IANA的时区对象字符串。P></

1
2
3
4
5
6
7
8
def make_tz_aware(dt, tz='UTC', is_dst=None):
   """Add timezone information to a datetime object, only if it is naive."""
    tz = dt.tzinfo or tz
    try:
        tz = pytz.timezone(tz)
    except AttributeError:
        pass
    return tz.localize(dt, is_dst=is_dst)

这似乎是datetime.localize()(or or should do,.inform().awarify())都接受字符串和对象时区tz to和for the argument UTC时区的默认,如果不是指定的。P></


我知道purely二法P></

1
2
3
4
5
from datetime import datetime
import pytz

naive = datetime.now()
aware = naive.replace(tzinfo=pytz.UTC)

前P></

1
aware = pytz.UTC.localize(naive)

当然你可以使用任何杂志,instead of UTC时区,P></


以本地时区(用add dateutil);P></

1
2
3
4
5
6
from dateutil import tz
import datetime

dt_unaware = datetime.datetime(2017, 6, 24, 12, 24, 36)

dt_aware = dt_unaware.replace(tzinfo=tz.tzlocal())

在回答unutbu' format of the s;自制的工具把手,事情是这样的句法,与更多的直觉。can be installed with皮普。P></

1
2
3
4
5
6
7
import datetime
import saturn

unaware = datetime.datetime(2011, 8, 15, 8, 15, 12, 0)
now_aware = saturn.fix_naive(unaware)

now_aware_madrid = saturn.fix_naive(unaware, 'Europe/Madrid')