Convert UTC datetime string to local datetime
我从来不用把时间转换成和从UTC转换。最近有一个请求让我的应用程序知道时区,我一直在循环运行。关于将本地时间转换为UTC的许多信息,我发现这是相当基本的(也许我做得也不对),但我找不到任何有关将UTC时间轻松转换为最终用户时区的信息。
简而言之,android应用程序会发送我(appengine应用程序)的数据,其中包含一个时间戳。要将时间戳存储到我使用的UTC时间,请执行以下操作:
1 | datetime.utcfromtimestamp(timestamp) |
这似乎奏效了。当我的应用程序存储数据时,它将在5小时前存储(我是EST-5)
数据存储在appengine的bigtable中,当检索到数据时,它会以字符串的形式出现,如下所示:
1 | "2011-01-21 02:37:21" |
如何将此字符串转换为用户正确时区中的日期时间?
另外,对于用户时区信息,建议的存储空间是什么?(您通常如何存储TZ信息,例如:"-5:00"或"est"等?)我确信第一个问题的答案可能包含一个参数,第二个问题的答案。
如果不想提供自己的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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) |
编辑扩展示例以显示
编辑2个固定的API用法以显示更好的入口点方法
编辑3包括时区自动检测方法(yarin)
这里有一个不依赖任何外部库的弹性方法:
1 2 3 4 5 6 7 | 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例子中的时间问题。以及埃里克·范·奥斯滕修正案中较小的时间问题。
作为一个有趣的脚注,上面计算的时区偏移量可能不同于以下看似等效的表达式,可能是由于夏令时规则的更改:
1 | offset = datetime.fromtimestamp(0) - datetime.utcfromtimestamp(0) # NO! |
更新:此代码段的缺点是使用当前时间的UTC偏移量,这可能与输入日期时间的UTC偏移量不同。有关其他解决方案,请参阅关于此答案的评论。
为了避开不同的时代,从过去的时间中抓取时代时间。我要做的是:
1 2 3 4 | def utc2local (utc): epoch = time.mktime(utc.timetuple()) offset = datetime.fromtimestamp (epoch) - datetime.utcfromtimestamp (epoch) return utc + offset |
请参阅有关TZINFO对象的日期时间文档。你必须实现你想要支持自己的时区。以下是文档底部的示例。
下面是一个简单的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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) |
产量
1 2 3 4 5 | 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 |
如果您想得到正确的结果,即使是与不明确的本地时间(例如,在DST转换期间)和/或本地UTC偏移量在本地时区的不同时间是不同的,则使用
1 2 3 4 5 6 7 8 | #!/usr/bin/env python from datetime import datetime import pytz # $ pip install pytz import tzlocal # $ pip install tzlocal local_timezone = tzlocal.get_localzone() # get pytz tzinfo utc_time = datetime.strptime("2011-01-21 02:37:21","%Y-%m-%d %H:%M:%S") local_time = utc_time.replace(tzinfo=pytz.utc).astimezone(local_timezone) |
如果使用django,则可以使用timezone.localtime方法(请参见https://docs.djangoproject.com/en/dev/topics/i18n/timezones/)。
1 2 3 4 5 6 | 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>) |
如果您不想使用除
如果您不是实例化开始日期的人,但您仍然可以在UTC时间创建一个幼稚的
1 2 3 4 5 6 | 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 |
小心不要错误地假定,如果您的时区当前是MDT,那么夏令时不适用于上述代码,因为它打印MST。您会注意到,如果您将月份更改为8月份,它将打印MDT。
另一种获取已知
1 2 3 4 5 6 7 8 9 10 11 12 | 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)) |
如果使用python 2.x,则可能需要对
您可以使用
1 2 3 4 5 6 7 | 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) |
给
这里有一个快速而肮脏的版本,它使用本地系统设置来计算时差。注意:如果需要转换为当前系统未运行的时区,则此操作将不起作用。我在英国标准时区的英国设置中测试过这个
1 2 3 4 5 6 7 8 9 10 11 12 | 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 |
传统上,我将时间延迟到前端——以时间戳或其他日期时间格式(UTC)从后端发送时间,然后让客户机计算出时区偏移量,并在适当的时区中呈现这些数据。
对于webapp来说,在javascript中很容易做到这一点——您可以使用内置方法很容易地计算出浏览器的时区偏移量,然后正确地从后端渲染数据。
从这里的答案中,您可以使用时间模块将UTC转换为计算机中设置的本地时间:
1 2 3 | 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) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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
你可以用箭头
1 2 3 4 5 6 7 | from datetime import datetime import arrow now = datetime.utcnow() print(arrow.get(now).to('local').format()) # '2018-04-04 15:59:24+02:00' |
你可以用任何东西喂