問題描述
Python - 從 DST 調整的本地時間到 UTC (Python - From DST-adjusted local time to UTC)
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.
(by Erik Ninn-Hansen、unutbu、agf)