Python - From DST-adjusted local time to UTC

2019-03-27 09:46发布

问题:

A specific bank has branches in all major cities in the world. They all open at 10:00 AM local time. If within a timezone that uses DST, then of course the local opening time also follows the DST-adjusted time. So how do I go from the local time to the utc time.

What I need is a function to_utc(localdt, tz) like this:

Arguments:

  • localdt: localtime, as naive datetime object, DST-adjusted
  • tz: timezone in the TZ-format, e.g. 'Europe/Berlin'

Returns:

  • datetime object, in UTC, timezone-aware

EDIT:

The biggest challenge is to detect whether the local time is in a period with DST, which also means that it is DST adjusted.

For 'Europe/Berlin' which has +1 DST in the summer:

  • Jan 1st 10:00 => Jan 1st 9:00 UTC
  • July 1st 10:00 => July 1st 8:00 UTC

For 'Africa/Lagos' which has no DST:

  • Jan 1st 10:00 => Jan 1st 9:00 UTC
  • July 1st 10:00 => July 1st 9:00 UTC

回答1:

Using pytz, and in particular its localize method:

import pytz
import datetime as dt

def to_utc(localdt,tz):
    timezone=pytz.timezone(tz)
    utc=pytz.utc
    return timezone.localize(localdt).astimezone(utc)

if __name__=='__main__':
    for tz in ('Europe/Berlin','Africa/Lagos'):
        for date in (dt.datetime(2011,1,1,10,0,0),
                 dt.datetime(2011,7,1,10,0,0),
                 ):
            print('{tz:15} {l} --> {u}'.format(
                tz=tz,
                l=date.strftime('%b %d %H:%M'),
                u=to_utc(date,tz).strftime('%b %d %H:%M %Z')))

yields

Europe/Berlin   Jan 01 10:00 --> Jan 01 09:00 UTC
Europe/Berlin   Jul 01 10:00 --> Jul 01 08:00 UTC
Africa/Lagos    Jan 01 10:00 --> Jan 01 09:00 UTC
Africa/Lagos    Jul 01 10:00 --> Jul 01 09:00 UTC


回答2:

from datetime import datetime, tzinfo, timedelta

class GMT1(tzinfo):
    def utcoffset(self, dt):
        return timedelta(hours=1)
    def dst(self, dt):
        return timedelta(0)
    def tzname(self,dt):
        return "Europe/Prague"
year, month, day = 2011, 7, 23
dt = datetime(year, month, day, 10)

class UTC(tzinfo):
    def utcoffset(self, dt):
        return timedelta(0)
    def dst(self, dt):
        return timedelta(0)
    def tzname(self,dt):
        return "UTC"

def utc(localt, tz):
    return localt.replace(tzinfo=tz).astimezone(UTC())

print utc(dt, GMT1())

New Version. This does what you want -- takes a naive datetime and a timezone and returns a UTC datetime.