将timez1 -aware datetime转换为Python中的本地时间。

时间:2022-01-19 15:45:56

How do you convert a timezone-aware datetime object to the equivalent non-timezone-aware datetime for the local timezone?

如何将timezone-aware datetime对象转换为本地时区的等效非timezone-aware datetime ?

My particular application uses Django (although, this is in reality a generic Python question):

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

import iso8601

....

....

date_str="2010-10-30T17:21:12Z"

....

....

d = iso8601.parse_date(date_str)

foo = app.models.FooModel(the_date=d)
foo.save()

This causes Django to throw an error:

这导致Django抛出一个错误:

raise ValueError("MySQL backend does not support timezone-aware datetimes.")

What I need is:

我需要的是:

d = iso8601.parse_date(date_str)
local_d = SOME_FUNCTION(d)
foo = app.models.FooModel(the_date=local_d)

What would SOME_FUNCTION be?

SOME_FUNCTION是什么?

4 个解决方案

#1


51  

In general, to convert an arbitrary timezone-aware datetime to a naive (local) datetime, I'd use the pytz module and astimezone to convert to local time, and replace to make the datetime naive:

一般来说,为了将一个任意的timezone-aware datetime转换为一个简单的(本地)datetime,我将使用pytz模块和astimezone来转换到本地时间,并替换为使datetime变得简单:

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)

But since your particular datetime seems to be in the UTC timezone, you could do this instead:

但是由于您的特定datetime似乎位于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)

By the way, you might be better off storing the datetimes as naive UTC datetimes instead of naive local datetimes. That way, your data is local-time agnostic, and you only convert to local-time or any other timezone when necessary. Sort of analogous to working in unicode as much as possible, and encoding only when necessary.

顺便说一下,您最好将datetimes存储为简单的UTC日期,而不是简单的本地datetimes。这样,您的数据是本地时间不可知的,您只能在需要时转换为本地时间或任何其他时区。类似于尽可能多地使用unicode,并且只在必要时进行编码。

So if you agree that storing the datetimes in naive UTC is the best way, then all you'd need to do is define:

因此,如果您同意在天真的UTC中存储datetimes是最好的方法,那么您需要做的就是定义:

local_d = d.replace(tzinfo=None)

#2


51  

In recent versions of Django (at least 1.4.1):

最近的Django版本(至少1.4.1):

from django.utils.timezone import localtime

result = localtime(some_time_object)

#3


2  

A portable robust solution should use the tz database. To get local timezone as pytz tzinfo object, use tzlocal module:

一个可移植的健壮的解决方案应该使用tz数据库。使用tzlocal模块获取本地时区为pytz tzinfo对象:

#!/usr/bin/env python
import iso8601
import tzlocal # $ pip install tzlocal

local_timezone = tzlocal.get_localzone()
aware_dt = iso8601.parse_date("2010-10-30T17:21:12Z") # some aware datetime object
naive_local_dt = aware_dt.astimezone(local_timezone).replace(tzinfo=None)

Note: it might be tempting to use something like:

注意:使用类似的东西可能很诱人:

#!/usr/bin/env python3
# ...
naive_local_dt = aware_dt.astimezone().replace(tzinfo=None)

but it may fail if the local timezone has a variable utc offset but python does not use a historical timezone database on a given platform.

但是,如果本地时区有一个变量utc偏移量,那么它可能会失败,但是python不会在给定的平台上使用历史时区数据库。

#4


0  

Using python-dateutil you can parse the date in iso-8561 format with dateutil.parsrser.parse() that will give you an aware datetime in UTC/Zulu timezone.

使用pythondateutil,您可以使用dateutil.parsrser.parse()来解析iso-8561格式的日期,它将在UTC/Zulu时区中为您提供一个感知的日期时间。

Using .astimezone() you can convert it to an aware datetime in another timezone.

使用.astimezone()可以将它转换为另一个时区中的感知日期时间。

Using .replace(tzinfo=None) will convert the aware datetime into a naive datetime.

使用.replace(tzinfo=None)将感知的datetime转换为一个简单的datetime。

from datetime import datetime
from dateutil import parser as datetime_parser
from dateutil.tz import tzutc,gettz

aware = datetime_parser.parse('2015-05-20T19:51:35.998931Z').astimezone(gettz("CET"))
naive = aware.replace(tzinfo=None)

In general the best idea is to convert all dates to UTC and store them that way, and convert them back to local as needed. I use aware.astimezone(tzutc()).replace(tzinfo=None) to make sure is in UTC and convert to naive.

一般来说,最好的办法是将所有的日期转换为UTC,并将它们存储起来,并根据需要将它们转换回本地。我使用aware.astimezone(tzutc()).replace(tzinfo=None),以确保UTC中并转换为幼稚。

#1


51  

In general, to convert an arbitrary timezone-aware datetime to a naive (local) datetime, I'd use the pytz module and astimezone to convert to local time, and replace to make the datetime naive:

一般来说,为了将一个任意的timezone-aware datetime转换为一个简单的(本地)datetime,我将使用pytz模块和astimezone来转换到本地时间,并替换为使datetime变得简单:

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)

But since your particular datetime seems to be in the UTC timezone, you could do this instead:

但是由于您的特定datetime似乎位于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)

By the way, you might be better off storing the datetimes as naive UTC datetimes instead of naive local datetimes. That way, your data is local-time agnostic, and you only convert to local-time or any other timezone when necessary. Sort of analogous to working in unicode as much as possible, and encoding only when necessary.

顺便说一下,您最好将datetimes存储为简单的UTC日期,而不是简单的本地datetimes。这样,您的数据是本地时间不可知的,您只能在需要时转换为本地时间或任何其他时区。类似于尽可能多地使用unicode,并且只在必要时进行编码。

So if you agree that storing the datetimes in naive UTC is the best way, then all you'd need to do is define:

因此,如果您同意在天真的UTC中存储datetimes是最好的方法,那么您需要做的就是定义:

local_d = d.replace(tzinfo=None)

#2


51  

In recent versions of Django (at least 1.4.1):

最近的Django版本(至少1.4.1):

from django.utils.timezone import localtime

result = localtime(some_time_object)

#3


2  

A portable robust solution should use the tz database. To get local timezone as pytz tzinfo object, use tzlocal module:

一个可移植的健壮的解决方案应该使用tz数据库。使用tzlocal模块获取本地时区为pytz tzinfo对象:

#!/usr/bin/env python
import iso8601
import tzlocal # $ pip install tzlocal

local_timezone = tzlocal.get_localzone()
aware_dt = iso8601.parse_date("2010-10-30T17:21:12Z") # some aware datetime object
naive_local_dt = aware_dt.astimezone(local_timezone).replace(tzinfo=None)

Note: it might be tempting to use something like:

注意:使用类似的东西可能很诱人:

#!/usr/bin/env python3
# ...
naive_local_dt = aware_dt.astimezone().replace(tzinfo=None)

but it may fail if the local timezone has a variable utc offset but python does not use a historical timezone database on a given platform.

但是,如果本地时区有一个变量utc偏移量,那么它可能会失败,但是python不会在给定的平台上使用历史时区数据库。

#4


0  

Using python-dateutil you can parse the date in iso-8561 format with dateutil.parsrser.parse() that will give you an aware datetime in UTC/Zulu timezone.

使用pythondateutil,您可以使用dateutil.parsrser.parse()来解析iso-8561格式的日期,它将在UTC/Zulu时区中为您提供一个感知的日期时间。

Using .astimezone() you can convert it to an aware datetime in another timezone.

使用.astimezone()可以将它转换为另一个时区中的感知日期时间。

Using .replace(tzinfo=None) will convert the aware datetime into a naive datetime.

使用.replace(tzinfo=None)将感知的datetime转换为一个简单的datetime。

from datetime import datetime
from dateutil import parser as datetime_parser
from dateutil.tz import tzutc,gettz

aware = datetime_parser.parse('2015-05-20T19:51:35.998931Z').astimezone(gettz("CET"))
naive = aware.replace(tzinfo=None)

In general the best idea is to convert all dates to UTC and store them that way, and convert them back to local as needed. I use aware.astimezone(tzutc()).replace(tzinfo=None) to make sure is in UTC and convert to naive.

一般来说,最好的办法是将所有的日期转换为UTC,并将它们存储起来,并根据需要将它们转换回本地。我使用aware.astimezone(tzutc()).replace(tzinfo=None),以确保UTC中并转换为幼稚。