Python 将带时区的UTC日期时间转换为本地

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和我的本地时间相加 提前谢谢 编辑:问题是不同的,因为它包括给定字符串中的时间差,重点是添加或缩短这个时间差,有时需要更改日期,如所提供的示例所示。我认为

我有一个字符串,带有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和我的本地时间相加

提前谢谢


编辑:问题是不同的,因为它包括给定字符串中的时间差,重点是添加或缩短这个时间差,有时需要更改日期,如所提供的示例所示。

我认为通过实现两个具体的
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编写的旧代码也可以工作。