简体   繁体   中英

Convert UTC datetime with timezone to local

I have a string with a date in UTC and tzinfo

"Thu, 01 Oct 2015 00:02:01 +0200"

How can I do to convert it to my local time so it outputs

"2015-10-02 02:02:01"

I tried

parser.parse("Thu, 01 Oct 2015 00:02:01 +0200")

but I can't find a way to sum this tzinfo to the time to get my local time.

Thanks in advance

Edit: The question is diferent as It includes time diference in the given string and the point is to add or sutract this time diference that sometimes requires to change the date as in the provided example.

Here's a stdlib solution:

#!/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

The input time format is rfc 5322 time format that is understood by email module . datetime.fromtimestamp() may fail for past/future dates if it doesn't use a historical time zone database on a given platform. A portable solution is to use pytz module, to get access to the tz database:

#!/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))

I think the following does what you want by implementing a couple of concrete tzinfo classes:

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'))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM