Python 将带时区的UTC日期时间转换为本地
我有一个字符串,带有UTC和tzinfo格式的日期Python 将带时区的UTC日期时间转换为本地,python,python-2.7,datetime,Python,Python 2.7,Datetime,我有一个字符串,带有UTC和tzinfo格式的日期 "Thu, 01 Oct 2015 00:02:01 +0200" 如何将其转换为本地时间以便输出 "2015-10-02 02:02:01" 我试过了 parser.parse("Thu, 01 Oct 2015 00:02:01 +0200") 但是我找不到一种方法把这些tzinfo和我的本地时间相加 提前谢谢 编辑:问题是不同的,因为它包括给定字符串中的时间差,重点是添加或缩短这个时间差,有时需要更改日期,如所提供的示例所示。我认为
"Thu, 01 Oct 2015 00:02:01 +0200"
如何将其转换为本地时间以便输出
"2015-10-02 02:02:01"
我试过了
parser.parse("Thu, 01 Oct 2015 00:02:01 +0200")
但是我找不到一种方法把这些tzinfo和我的本地时间相加
提前谢谢
编辑:问题是不同的,因为它包括给定字符串中的时间差,重点是添加或缩短这个时间差,有时需要更改日期,如所提供的示例所示。我认为通过实现两个具体的
tzinfo
类,以下内容可以满足您的需要:
from datetime import datetime, timedelta, tzinfo
import time as _time
_ZERO = timedelta(0)
_STDOFFSET = timedelta(seconds=-_time.timezone)
if _time.daylight:
_DSTOFFSET = timedelta(seconds=-_time.altzone)
else:
_DSTOFFSET = _STDOFFSET
_DSTDIFF = _DSTOFFSET - _STDOFFSET
class UTC(tzinfo):
""" Concrete tzinfo time zone class for UTC
"""
def utcoffset(self, dt):
return _ZERO
def tzname(self, dt):
return "UTC"
def dst(self, dt):
return _ZERO
UTC = UTC()
class LocalTimezone(tzinfo):
""" Concrete tzinfo time zone class for current timezone
"""
def utcoffset(self, dt):
if self._isdst(dt):
return _DSTOFFSET
else:
return _STDOFFSET
def dst(self, dt):
if self._isdst(dt):
return _DSTDIFF
else:
return _ZERO
def tzname(self, dt):
return _time.tzname[self._isdst(dt)]
# everything depends on this private method which assumes 'dt' argument
# is in local time
def _isdst(self, dt):
tt = (dt.year, dt.month, dt.day,
dt.hour, dt.minute, dt.second,
dt.weekday(), 0, -1) # last -1 means dst unknown (mktime will fill in)
stamp = _time.mktime(tt) # mktime returns secs
tt = _time.localtime(stamp) # localtime returns time_struct with tm_isdst attribute
return tt.tm_isdst > 0
LOCAL = LocalTimezone()
stamp = 'Thu, 01 Oct 2015 00:02:01 +0200'
dt = datetime(*_time.strptime(' '.join(stamp.split()[:-1]),
'%a, %d %b %Y %H:%M:%S')[:6], tzinfo=UTC)
local_dt = dt.astimezone(LOCAL)
print(local_dt.strftime('%Y-%M-%d %H:%M:%S'))
我认为下面通过实现几个具体的
tzinfo
类实现了您想要的功能:
from datetime import datetime, timedelta, tzinfo
import time as _time
_ZERO = timedelta(0)
_STDOFFSET = timedelta(seconds=-_time.timezone)
if _time.daylight:
_DSTOFFSET = timedelta(seconds=-_time.altzone)
else:
_DSTOFFSET = _STDOFFSET
_DSTDIFF = _DSTOFFSET - _STDOFFSET
class UTC(tzinfo):
""" Concrete tzinfo time zone class for UTC
"""
def utcoffset(self, dt):
return _ZERO
def tzname(self, dt):
return "UTC"
def dst(self, dt):
return _ZERO
UTC = UTC()
class LocalTimezone(tzinfo):
""" Concrete tzinfo time zone class for current timezone
"""
def utcoffset(self, dt):
if self._isdst(dt):
return _DSTOFFSET
else:
return _STDOFFSET
def dst(self, dt):
if self._isdst(dt):
return _DSTDIFF
else:
return _ZERO
def tzname(self, dt):
return _time.tzname[self._isdst(dt)]
# everything depends on this private method which assumes 'dt' argument
# is in local time
def _isdst(self, dt):
tt = (dt.year, dt.month, dt.day,
dt.hour, dt.minute, dt.second,
dt.weekday(), 0, -1) # last -1 means dst unknown (mktime will fill in)
stamp = _time.mktime(tt) # mktime returns secs
tt = _time.localtime(stamp) # localtime returns time_struct with tm_isdst attribute
return tt.tm_isdst > 0
LOCAL = LocalTimezone()
stamp = 'Thu, 01 Oct 2015 00:02:01 +0200'
dt = datetime(*_time.strptime(' '.join(stamp.split()[:-1]),
'%a, %d %b %Y %H:%M:%S')[:6], tzinfo=UTC)
local_dt = dt.astimezone(LOCAL)
print(local_dt.strftime('%Y-%M-%d %H:%M:%S'))
下面是一个stdlib解决方案:
#!/usr/bin/env python
from datetime import datetime
from email.utils import parsedate_tz, mktime_tz
timestamp = mktime_tz(parsedate_tz("Thu, 01 Oct 2015 00:02:01 +0200"))
print(datetime.fromtimestamp(timestamp)) # get local time
输入时间格式为datetime.fromtimestamp()
如果不使用给定平台上的历史时区数据库,则过去/将来的日期可能会失败。便携式解决方案是使用pytz
模块访问tz数据库:
#!/usr/bin/env python
from datetime import datetime
from email.utils import parsedate_tz, mktime_tz
import tzlocal # $ pip install tzlocal
local_timezone = tzlocal.get_localzone() # return pytz tzinfo
timestamp = mktime_tz(parsedate_tz("Thu, 01 Oct 2015 00:02:01 +0200"))
print(datetime.fromtimestamp(timestamp, local_timezone))
下面是一个stdlib解决方案:
#!/usr/bin/env python
from datetime import datetime
from email.utils import parsedate_tz, mktime_tz
timestamp = mktime_tz(parsedate_tz("Thu, 01 Oct 2015 00:02:01 +0200"))
print(datetime.fromtimestamp(timestamp)) # get local time
输入时间格式为datetime.fromtimestamp()
如果不使用给定平台上的历史时区数据库,则过去/将来的日期可能会失败。便携式解决方案是使用pytz
模块访问tz数据库:
#!/usr/bin/env python
from datetime import datetime
from email.utils import parsedate_tz, mktime_tz
import tzlocal # $ pip install tzlocal
local_timezone = tzlocal.get_localzone() # return pytz tzinfo
timestamp = mktime_tz(parsedate_tz("Thu, 01 Oct 2015 00:02:01 +0200"))
print(datetime.fromtimestamp(timestamp, local_timezone))
您的意思是
datetime.strtime(dte,“%a,%d%b%Y%H:%M:%S%z”).astimezone(tz=None)
?@Prune不太一样,在这种情况下,时区本身是未知的,只有偏移量(作为字符串)。它可能仍然是一个副本,但我不知道它可能在哪里。@Padraiccanningham这取决于平台-Windows无法识别%z
,尽管我认为他们可能已经在Python 3的某些版本中修复了它。@MarkRansom,我认为它适用于>=3.3,但我从未使用过windows,因此我可能会出错。你的意思是datetime.strtime(dte,“%a,%d%b%Y%H:%M:%S%z”)。astimezone(tz=None)
?@Prune不太一样,在这种情况下,时区本身是未知的,只有偏移量(作为字符串)。它可能仍然是一个副本,但我不知道它可能在哪里。@PadraicCunningham这取决于平台-Windows无法识别%z
,尽管我认为他们可能已经在Python 3的某些版本中修复了这一点。@MarkRansom,我认为它适合>=3.3,但我从未使用过Windows,所以我可能是错的。@Uau!这确实有效,但我从来没有想到需要做很多工作。我认为这可以用几行代码来完成。@Pep:LocalTimezone
使用,如果本地utc偏移量在过去可能不同,它肯定会在过去/将来的日期失败。是的,需要相当多的代码,因为股票Python只定义了一个抽象的tzinfo
类。尽管如此,我所提供的只是一个尝试,只需要一个足够的具体实现,就可以用一种通用的方式,仅使用内置模块来解决您的问题。像模块这样的替代方案包含了更多的代码。之所以需要这么多代码,是因为一个看似简单但非常惯用的实践(具有讽刺意味的是,这种实践随着时间的推移而不断变化)具有惊人的复杂性。您是否理解utc偏移量在不同的时间可能不同(与DST转换无关)因此,在这种情况下,time.timezone
这是一个常数,不可能提供正确的答案!这确实有效,但我从来没有想到需要做很多工作。我认为这可以用几行代码来完成。@Pep:LocalTimezone
使用,如果本地utc偏移量在过去可能不同,它肯定会在过去/将来的日期失败。是的,需要相当多的代码,因为股票Python只定义了一个抽象的tzinfo
类。尽管如此,我所提供的只是一个尝试,只需要一个足够的具体实现,就可以用一种通用的方式,仅使用内置模块来解决您的问题。像模块这样的替代方案包含了更多的代码。之所以需要这么多代码,是因为一个看似简单但非常惯用的实践(具有讽刺意味的是,这种实践随着时间的推移而不断变化)具有惊人的复杂性。您是否理解utc偏移量在不同的时间可能不同(与DST转换无关)因此,time.timezone
这是一个常量,在这种情况下不可能提供正确的答案?输入时间格式也与较早的规范兼容,这是Python 2.x所引用的。很好的便携式和简洁的答案+1@martineau:rfc 5322淘汰了2822是的,我知道…只是指出了为什么按照rfc 2822编写的旧代码也可以工作。输入时间格式也与旧规范兼容,这也是Python 2.x所引用的。很好的便携式和简洁的答案+1@martineau:rfc 5322废弃2822是的,我知道…只是指出了为什么按照rfc 2822编写的旧代码也可以工作。