Mar*_*zzi 446 python timezone datetime
我需要做什么
我有一个时区不知道的日期时间对象,我需要添加一个时区,以便能够将其与其他时区感知日期时间对象进行比较.我不想将我的整个应用程序转换为时区,而不是因为这个遗留案例.
我试过的
首先,要证明问题:
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
Run Code Online (Sandbox Code Playgroud)
首先,我尝试了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
>>>
Run Code Online (Sandbox Code Playgroud)
这失败并不令人惊讶,因为它实际上是在尝试进行转换.替换似乎是一个更好的选择(根据Python:如何获得"timezone aware"的datetime.today()值?):
>>> 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
>>>
Run Code Online (Sandbox Code Playgroud)
但正如你所看到的,replace似乎设置了tzinfo,但没有让对象知道.我正准备在解析它之前回过头来修改输入字符串以获得时区(我正在使用dateutil进行解析,如果这很重要),但这看起来非常糟糕.
另外,我在python 2.6和python 2.7中都尝试了这个,结果相同.
上下文
我正在为一些数据文件编写解析器.我需要支持一种旧格式,其中日期字符串没有时区指示符.我已经修复了数据源,但我仍然需要支持旧数据格式.遗留数据的一次转换不是针对各种商业BS原因的选项.虽然一般来说,我不喜欢硬编码默认时区的想法,在这种情况下,它似乎是最好的选择.我非常有信心地知道所有遗留数据都是UTC格式的,所以我准备接受在这种情况下违约的风险.
unu*_*tbu 528
通常,要使天真的日期时间可识别,请使用localize方法:
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
Run Code Online (Sandbox Code Playgroud)
对于UTC时区,没有必要使用,localize
因为没有夏令时计算来处理:
now_aware = unaware.replace(tzinfo=pytz.UTC)
Run Code Online (Sandbox Code Playgroud)
作品.(.replace
返回一个新的日期时间;它不会修改unaware
.)
小智 124
所有这些示例都使用外部模块,但您只需使用datetime模块即可获得相同的结果,如本SO答案中所示:
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'
Run Code Online (Sandbox Code Playgroud)
依赖性较少,没有pytz问题.
注意:如果您希望将它与python3和python2一起使用,您也可以使用它来进行时区导入(硬编码为UTC):
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()
Run Code Online (Sandbox Code Playgroud)
Sér*_*gio 76
我曾经使用过dt_aware和dt_unware
dt_unaware = dt_aware.replace(tzinfo=None)
Run Code Online (Sandbox Code Playgroud)
和dt_unware到dt_aware
from pytz import timezone
localtz = timezone('Europe/Lisbon')
dt_aware = localtz.localize(dt_unware)
Run Code Online (Sandbox Code Playgroud)
但之前的回答也是一个很好的解决方案.
小智 40
我在Django中使用此语句将不知不觉的时间转换为意识到:
from django.utils import timezone
dt_aware = timezone.make_aware(dt_unaware, timezone.get_current_timezone())
Run Code Online (Sandbox Code Playgroud)
xjc*_*jcl 20
Python 3.9 添加了zoneinfo
模块,所以现在只需要标准库!
from zoneinfo import ZoneInfo
from datetime import datetime
unaware = datetime(2020, 10, 31, 12)
Run Code Online (Sandbox Code Playgroud)
附上时区:
>>> unaware.replace(tzinfo=ZoneInfo('Asia/Tokyo'))
datetime.datetime(2020, 10, 31, 12, 0, tzinfo=zoneinfo.ZoneInfo(key='Asia/Tokyo'))
>>> str(_)
'2020-10-31 12:00:00+09:00'
Run Code Online (Sandbox Code Playgroud)
附加系统的本地时区:
>>> unaware.replace(tzinfo=ZoneInfo('localtime'))
datetime.datetime(2020, 10, 31, 12, 0, tzinfo=zoneinfo.ZoneInfo(key='localtime'))
>>> str(_)
'2020-10-31 12:00:00+01:00'
Run Code Online (Sandbox Code Playgroud)
随后它被正确转换为其他时区:
>>> unaware.replace(tzinfo=ZoneInfo('localtime')).astimezone(ZoneInfo('Asia/Tokyo'))
datetime.datetime(2020, 10, 31, 20, 0, tzinfo=backports.zoneinfo.ZoneInfo(key='Asia/Tokyo'))
>>> str(_)
'2020-10-31 20:00:00+09:00'
Run Code Online (Sandbox Code Playgroud)
Windows 没有系统时区数据库,所以这里需要一个额外的包:
pip install tzdata
Run Code Online (Sandbox Code Playgroud)
有一个 backport 允许zoneinfo
在Python 3.6 到 3.8 中使用:
pip install backports.zoneinfo
Run Code Online (Sandbox Code Playgroud)
然后:
from backports.zoneinfo import ZoneInfo
Run Code Online (Sandbox Code Playgroud)
pao*_*lov 12
我同意之前的答案,如果你可以在UTC开始,那就没问题了.但我认为这也是人们使用具有非UTC本地时区的日期时间的tz感知值的常见情况.
如果您只是按名称去,可能会推断replace()将适用并生成正确的日期时间感知对象.不是这种情况.
替换(tzinfo = ...)似乎在其行为中是随机的.因此没用.不要用这个!
localize是正确使用的功能.例:
localdatetime_aware = tz.localize(datetime_nonaware)
Run Code Online (Sandbox Code Playgroud)
或者更完整的例子:
import pytz
from datetime import datetime
pytz.timezone('Australia/Melbourne').localize(datetime.now())
Run Code Online (Sandbox Code Playgroud)
给我一个当前本地时间的时区感知日期时间值:
datetime.datetime(2017, 11, 3, 7, 44, 51, 908574, tzinfo=<DstTzInfo 'Australia/Melbourne' AEDT+11:00:00 DST>)
Run Code Online (Sandbox Code Playgroud)
Har*_*eno 10
对于那些只想了解时区的日期时间的人
import datetime
datetime.datetime(2019, 12, 7, tzinfo=datetime.timezone.utc)
Run Code Online (Sandbox Code Playgroud)
对于那些想要从 python 3.9 stdlib 开始的非 utc 时区的日期时间的人
import datetime
from zoneinfo import ZoneInfo
datetime.datetime(2019, 12, 7, tzinfo=ZoneInfo("America/Los_Angeles"))
Run Code Online (Sandbox Code Playgroud)
这编纂了@Sérgio和@ unutbu的答案.它将与pytz.timezone
对象或IANA时区字符串"正常工作" .
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)
Run Code Online (Sandbox Code Playgroud)
这似乎是datetime.localize()
(或.inform()
或.awarify()
)应该做什么,接受tz参数的字符串和时区对象,如果没有指定时区,则默认为UTC.
为了添加本地时区;(使用dateutil)
from dateutil import tz
import datetime
dt_unaware = datetime.datetime(2017, 6, 24, 12, 24, 36)
dt_aware = dt_unaware.replace(tzinfo=tz.tzlocal())
Run Code Online (Sandbox Code Playgroud)
还有另一种让datetime
对象不幼稚的方法:
>>> from datetime import datetime, timezone
>>> datetime.now(timezone.utc)
datetime.datetime(2021, 5, 1, 22, 51, 16, 219942, tzinfo=datetime.timezone.utc)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
274820 次 |
最近记录: |