![](/img/trans.png)
[英]Python Convert String to Local DateTime to UTC DateTime
[英]Convert UTC datetime string to local datetime
我从来不需要在 UTC 之间转换时间。 最近有一个要求让我的应用程序能够感知时区,我一直在绕圈子。 很多关于将本地时间转换为 UTC 的信息,我发现这些信息相当基本(也许我也做错了),但我找不到任何关于轻松将 UTC 时间转换为最终用户时区的信息。
简而言之,android 应用程序向我发送(appengine 应用程序)数据,并且在该数据中是一个时间戳。 将该时间戳存储到我正在使用的UTC时间:
datetime.utcfromtimestamp(timestamp)
如果您不想提供自己的tzinfo
对象,请查看python-dateutil库。 它在zoneinfo (Olson) 数据库之上提供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)
这是一个不依赖任何外部库的弹性方法:
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
请参阅有关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
如果您想获得正确的结果,即使在对应于不明确的本地时间(例如,在 DST 转换期间)和/或本地时区不同时间的本地 utc 偏移量也不同,请使用pytz
时区:
#!/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)
如果您不想使用除datetime
之外的任何其他模块,此答案应该会有所帮助。
datetime.utcfromtimestamp(timestamp)
返回一个天真的datetime
对象(不是一个有意识的对象)。 有意识的人是时区意识的,而幼稚的则不是。 如果您想在时区之间进行转换(例如在 UTC 和本地时间之间),您需要一个有意识的。
如果您不是实例化开始日期的人,但您仍然可以在 UTC 时间创建一个简单的datetime
对象,您可能想尝试使用这个 Python 3.x 代码来转换它:
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。 您会注意到,如果将月份更改为八月,它将打印 MDT。
获取感知datetime
对象(也在 Python 3.x 中)的另一种简单方法是使用指定的时区开始创建它。 这是一个使用 UTC 的示例:
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,你可能需要继承datetime.tzinfo
并使用它来帮助你创建一个有意识的datetime
对象,因为datetime.timezone
在 Python 2.x 中不存在。
如果使用 Django,则可以使用timezone.localtime
方法:
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>)
你可以使用箭头
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 字符串等
将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()))
您可以使用calendar.timegm
将您的时间转换为 Unix 纪元以来的time.localtime
,并将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 时区)。
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_tz_example_str = '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'
# call my function here
local_tz_str = utc_str_to_local_str(utc_tz_example_str, utc_fmt, local_fmt)
print(local_tz_str) # 2018-10-17T08:00:00+08:00
当我输入utc_tz_example_str
= 2018-10-17T00:00:00.111Z 时,(UTC +00:00)
然后我会得到local_tz_str
= 2018-10-17T08:00:00+08:00 (我的目标时区 +08:00)
参数utc_format
是由您的特定utc_tz_example_str
确定的格式。
参数local_fmt
是最终所需的格式。
就我而言,我想要的格式是%Y-%m-%dT%H:%M:%S+08:00
( +08:00 时区)。 您应该构建所需的格式。
我传统上将此推迟到前端 - 从后端发送时间作为时间戳或其他一些 UTC 日期时间格式,然后让客户端计算出时区偏移量并在正确的时区中呈现这些数据。
对于 web 应用程序,这在 javascript 中很容易做到——您可以使用内置方法很容易地找出浏览器的时区偏移量,然后从后端正确呈现数据。
从这里的答案,您可以使用 time 模块将 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)
以下在美国西部的云环境中对我有用:
import datetime
import pytz
#set the timezone
tzInfo = pytz.timezone('America/Los_Angeles')
dt = datetime.datetime.now(tz=tzInfo)
print(dt)
这是一个快速而肮脏的版本,它使用本地系统设置来计算时差。 注意:如果您需要转换为当前系统未运行的时区,这将不起作用。我已在 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
这对我有用:
from django.utils import timezone
from datetime import timedelta,datetime
ist_time = timezone.now() + timedelta(hours=5,minutes=30)
#second method
ist_time = datetime.now() + timedelta(hours=5,minutes=30)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.