将UTC日期时间字符串转换为本地日期时间

时间:2011-01-22 20:14:51

标签: python datetime utc localtime

我从来没有把时间转换成UTC。最近有一个请求要让我的应用程序能够识别时区,而且我一直在圈子里跑。关于将本地时间转换为UTC的大量信息,我发现它相当基本(也许我也做错了),但我找不到任何有关将UTC时间轻松转换为最终用户时区的信息。

简而言之,Android应用程序向我发送(appengine app)数据,并在该数据中是时间戳。要将时间戳存储到我正在使用的时间:

datetime.utcfromtimestamp(timestamp)

这似乎有效。当我的应用程序存储数据时,它将提前5小时存储(我是EST-5)

数据存储在appengine的BigTable上,当检索到它时,它就像一个字符串一样:

"2011-01-21 02:37:21"

如何在用户正确的时区将此字符串转换为DateTime?

此外,用户时区信息的建议存储量是多少? (你如何存储tz信息,即:“-5:00”或“EST”等等?)我确信我的第一个问题的答案可能包含一个参数,第二个答案。

14 个答案:

答案 0 :(得分:335)

如果您不想提供自己的tzinfo个对象,请查看python-dateutil库。它在zoneinfo (Olson) database之上提供tzinfo个实现,以便您可以通过一个有点规范的名称来引用时区规则。

from datetime import datetime
from dateutil import tz

# METHOD 1: Hardcode zones:
from_zone = tz.gettz('UTC')
to_zone = tz.gettz('America/New_York')

# METHOD 2: Auto-detect zones:
from_zone = tz.tzutc()
to_zone = tz.tzlocal()

# utc = datetime.utcnow()
utc = datetime.strptime('2011-01-21 02:37:21', '%Y-%m-%d %H:%M:%S')

# Tell the datetime object that it's in UTC time zone since 
# datetime objects are 'naive' by default
utc = utc.replace(tzinfo=from_zone)

# Convert time zone
central = utc.astimezone(to_zone)

修改展开的示例以显示strptime用法

编辑2 修复API使用情况以显示更好的入口点方法

编辑3 包含时区的自动检测方法(Yarin)

答案 1 :(得分:36)

这是一种不依赖于任何外部库的弹性方法:

from datetime import datetime
import time

def datetime_from_utc_to_local(utc_datetime):
    now_timestamp = time.time()
    offset = datetime.fromtimestamp(now_timestamp) - datetime.utcfromtimestamp(now_timestamp)
    return utc_datetime + offset

这避免了DelboyJay示例中的计时问题。而且Erik van Oosten的修正案中的时间问题较少。

作为一个有趣的脚注,上面计算的时区偏移量可能与以下看似相同的表达式不同,可能是由于夏令时规则的变化:

offset = datetime.fromtimestamp(0) - datetime.utcfromtimestamp(0) # NO!

更新:此代码段具有使用当前时间的UTC偏移量的弱点,该偏移量可能与输入日期时间的UTC偏移量不同。有关其他解决方案,请参阅此答案的评论。

要绕过不同的时间,从传入的时间开始抓住纪元时间。这就是我的工作:

def utc2local (utc):
    epoch = time.mktime(utc.timetuple())
    offset = datetime.fromtimestamp (epoch) - datetime.utcfromtimestamp (epoch)
    return utc + offset

答案 2 :(得分:21)

请参阅datetime对象的tzinfo文档。您必须实现自己想要支持的时区。这些是文档底部的示例。

这是一个简单的例子:

from datetime import datetime,tzinfo,timedelta

class Zone(tzinfo):
    def __init__(self,offset,isdst,name):
        self.offset = offset
        self.isdst = isdst
        self.name = name
    def utcoffset(self, dt):
        return timedelta(hours=self.offset) + self.dst(dt)
    def dst(self, dt):
            return timedelta(hours=1) if self.isdst else timedelta(0)
    def tzname(self,dt):
         return self.name

GMT = Zone(0,False,'GMT')
EST = Zone(-5,False,'EST')

print datetime.utcnow().strftime('%m/%d/%Y %H:%M:%S %Z')
print datetime.now(GMT).strftime('%m/%d/%Y %H:%M:%S %Z')
print datetime.now(EST).strftime('%m/%d/%Y %H:%M:%S %Z')

t = datetime.strptime('2011-01-21 02:37:21','%Y-%m-%d %H:%M:%S')
t = t.replace(tzinfo=GMT)
print t
print t.astimezone(EST)

输出

01/22/2011 21:52:09 
01/22/2011 21:52:09 GMT
01/22/2011 16:52:09 EST
2011-01-21 02:37:21+00:00
2011-01-20 21:37:21-05:00a

答案 3 :(得分:14)

如果您希望获得正确的结果,即使对应于模糊的本地时间(例如,在DST转换期间)和/或本地时区的不同时间本地utc偏移量不同,那么请使用{ {1}}时区:

pytz

答案 4 :(得分:6)

如果使用django,您可以使用timezone.localtime方法(请参阅https://docs.djangoproject.com/en/dev/topics/i18n/timezones/)。

from django.utils import timezone
date 
# datetime.datetime(2014, 8, 1, 20, 15, 0, 513000, tzinfo=<UTC>)

timezone.localtime(date)
# datetime.datetime(2014, 8, 1, 16, 15, 0, 513000, tzinfo=<DstTzInfo 'America/New_York' EDT-1 day, 20:00:00 DST>)

答案 5 :(得分:5)

如果您不想使用GetLastError()以外的任何其他模块,此答案应该会有所帮助。

datetime返回一个天真的datetime.utcfromtimestamp(timestamp)对象(不是一个知道的对象)。意识到的是时区意识,天真不是。如果要在时区之间进行转换(例如,在UTC和本地时间之间),您需要知道一个。

如果你不是实例化日期开始的那个,但你仍然可以在UTC时间创建一个天真的datetime对象,你可能想尝试这个Python 3.x代码来转换它:

datetime

小心不要误以为如果你的时区目前是MDT,那么夏令时不能使用上面的代码,因为它会打印MST。您需要注意的是,如果您将月份更改为8月,则会打印MDT。

另一种获取感知import datetime d=datetime.datetime.strptime("2011-01-21 02:37:21", "%Y-%m-%d %H:%M:%S") #Get your naive datetime object d=d.replace(tzinfo=datetime.timezone.utc) #Convert it to an aware datetime object in UTC time. d=d.astimezone() #Convert it to your local timezone (still aware) print(d.strftime("%d %b %Y (%I:%M:%S:%f %p) %Z")) #Print it with a directive of choice 对象(也在Python 3.x中)的简单方法是使用指定的时区创建它。这是一个使用UTC的例子:

datetime

如果你使用Python 2.x,那么你可能必须继承import datetime, sys aware_utc_dt_obj=datetime.datetime.now(datetime.timezone.utc) #create an aware datetime object dt_obj_local=aware_utc_dt_obj.astimezone() #convert it to local time #The following section is just code for a directive I made that I liked. if sys.platform=="win32": directive="%#d %b %Y (%#I:%M:%S:%f %p) %Z" else: directive="%-d %b %Y (%-I:%M:%S:%f %p) %Z" print(dt_obj_local.strftime(directive)) 并使用它来帮助你创建一个有意识的datetime.tzinfo对象,因为datetime没有&#39 ; t存在于Python 2.x中。

答案 6 :(得分:1)

我传统上将此推迟到前端 - 从后端发送时间作为时间戳或UTC中的其他日期时间格式,然后让客户端找出时区偏移并在适当的时区呈现此数据。

对于一个webapp,这在javascript中很容易做到 - 你可以使用内置方法很容易地找出浏览器的时区偏移量,然后正确地从后端渲染数据。

答案 7 :(得分:1)

您可以使用calendar.timegm将您的时间转换为自Unix纪元以来的秒数和time.localtime转换回来的时间:

import calendar
import time

time_tuple = time.strptime("2011-01-21 02:37:21", "%Y-%m-%d %H:%M:%S")
t = calendar.timegm(time_tuple)

print time.ctime(t)

给出Fri Jan 21 05:37:21 2011(因为我在UTC + 03:00时区)。

答案 8 :(得分:1)

franksands中的答案合并为一种方便的方法。

import calendar
import datetime

def to_local_datetime(utc_dt):
    """
    convert from utc datetime to a locally aware datetime according to the host timezone

    :param utc_dt: utc datetime
    :return: local timezone datetime
    """
    return datetime.datetime.fromtimestamp(calendar.timegm(utc_dt.timetuple()))

答案 9 :(得分:1)

以下在美国西部的云环境中对我有用:

import datetime
import pytz

#set the timezone
tzInfo = pytz.timezone('America/Los_Angeles')
dt = datetime.datetime.now(tz=tzInfo)
print(dt)

答案 10 :(得分:0)

这是一个快速而又脏的版本,它使用本地系统设置来计算时差。注意:如果您需要转换为当前系统未运行的时区,则无法使用此功能。我已使用BST时区下的英国设置对此进行了测试

from datetime import datetime
def ConvertP4DateTimeToLocal(timestampValue):
   assert isinstance(timestampValue, int)

   # get the UTC time from the timestamp integer value.
   d = datetime.utcfromtimestamp( timestampValue )

   # calculate time difference from utcnow and the local system time reported by OS
   offset = datetime.now() - datetime.utcnow()

   # Add offset to UTC time and return it
   return d + offset

答案 11 :(得分:0)

您可以使用arrow

from datetime import datetime
import arrow

now = datetime.utcnow()

print(arrow.get(now).to('local').format())
# '2018-04-04 15:59:24+02:00'

您可以向arrow.get()提供任何内容。时间戳,iso字符串等

答案 12 :(得分:0)

import datetime

def utc_str_to_local_str(utc_str: str, utc_format: str, local_format: str):
    """
    :param utc_str: UTC time string
    :param utc_format: format of UTC time string
    :param local_format: format of local time string
    :return: local time string
    """
    temp1 = datetime.datetime.strptime(utc_str, utc_format)
    temp2 = temp1.replace(tzinfo=datetime.timezone.utc)
    local_time = temp2.astimezone()
    return local_time.strftime(local_format)

utc = '2018-10-17T00:00:00.111Z'
utc_fmt = '%Y-%m-%dT%H:%M:%S.%fZ'
local_fmt = '%Y-%m-%dT%H:%M:%S+08:00'
local_string = utc_str_to_local_str(utc, utc_fmt, local_fmt)
print(local_string)   # 2018-10-17T08:00:00+08:00

例如,我的时区为“ +08:00 ”。输入utc = 2018-10-17T00:00:00.111Z ,那么我将得到输出= 2018-10-17T08:00:00 + 08:00

答案 13 :(得分:0)

从答案here中,您可以使用时间模块将utc转换为计算机中设置的本地时间:

utc_time = time.strptime("2018-12-13T10:32:00.000", "%Y-%m-%dT%H:%M:%S.%f")
utc_seconds = calendar.timegm(utc_time)
local_time = time.localtime(utc_seconds)
相关问题