在Python中将时区感知日期时间转换为本地时间

kes*_*kes 37 python django datetime iso8601

如何将时区感知日期时间对象转换为本地时区的等效非时区感知日期时间?

我的特定应用程序使用Django(虽然,这实际上是一个通用的Python问题):

import iso8601
Run Code Online (Sandbox Code Playgroud)

....

date_str="2010-10-30T17:21:12Z"
Run Code Online (Sandbox Code Playgroud)

....

d = iso8601.parse_date(date_str)

foo = app.models.FooModel(the_date=d)
foo.save()
Run Code Online (Sandbox Code Playgroud)

这会导致Django抛出错误:

raise ValueError("MySQL backend does not support timezone-aware datetimes.")
Run Code Online (Sandbox Code Playgroud)

我需要的是:

d = iso8601.parse_date(date_str)
local_d = SOME_FUNCTION(d)
foo = app.models.FooModel(the_date=local_d)
Run Code Online (Sandbox Code Playgroud)

什么会SOME_FUNCTION是什么?

use*_*876 63

在Django的最新版本中(至少1.4.1):

from django.utils.timezone import localtime

result = localtime(some_time_object)
Run Code Online (Sandbox Code Playgroud)

  • `localtime()`可能使用可能与本地时区不同的`settings.TIME_ZONE`,例如,如果你没有设置它,那么它默认为''America/Chicago'.如果`localtime()`不使用`settings.TIME_ZONE`那么它使用[broken(根据其文档)`LocalTimezone()`](https://github.com/django/django/blob/master/django/ utils的/ timezone.py#L81) (4认同)

unu*_*tbu 60

通常,要将任意时区感知日期时间转换为天真(本地)日期时间,我将使用该pytz模块并astimezone转换为本地时间,replace并使日期时间变得幼稚:

In [76]: import pytz

In [77]: est=pytz.timezone('US/Eastern')

In [78]: d.astimezone(est)
Out[78]: datetime.datetime(2010, 10, 30, 13, 21, 12, tzinfo=<DstTzInfo 'US/Eastern' EDT-1 day, 20:00:00 DST>)

In [79]: d.astimezone(est).replace(tzinfo=None)
Out[79]: datetime.datetime(2010, 10, 30, 13, 21, 12)
Run Code Online (Sandbox Code Playgroud)

但由于您的特定日期时间似乎在UTC时区,您可以这样做:

In [65]: d
Out[65]: datetime.datetime(2010, 10, 30, 17, 21, 12, tzinfo=tzutc())

In [66]: import datetime

In [67]: import calendar

In [68]: datetime.datetime.fromtimestamp(calendar.timegm(d.timetuple()))
Out[68]: datetime.datetime(2010, 10, 30, 13, 21, 12)
Run Code Online (Sandbox Code Playgroud)

顺便说一句,你可能最好将日期时间存储为天真的UTC日期时间而不是天真的本地日期时间.这样,您的数据与本地时间无关,只在必要时转换为本地时间或任何其他时区.类似于尽可能多地使用unicode,并且仅在必要时进行编码.

因此,如果您同意以天真的UTC存储日期时间是最佳方式,那么您需要做的就是定义:

local_d = d.replace(tzinfo=None)
Run Code Online (Sandbox Code Playgroud)