我现在能想到的最好的就是这种怪异:
>>> datetime.utcnow() \ ... .replace(tzinfo=pytz.UTC) \ ... .astimezone(pytz.timezone("Australia/Melbourne")) \ ... .replace(hour=0,minute=0,second=0,microsecond=0) \ ... .astimezone(pytz.UTC) \ ... .replace(tzinfo=None) datetime.datetime(2008, 12, 16, 13, 0)
即,用英语,获取当前时间(以UTC为单位),将其转换为其他时区,将时间设置为午夜,然后转换回UTC.
我不只是使用now()或localtime(),因为它会使用服务器的时区,而不是用户的时区.
我不禁感到我错过了什么,有什么想法吗?
我认为如果你这样做,你可以减少一些方法调用:
>>> from datetime import datetime >>> datetime.now(pytz.timezone("Australia/Melbourne")) \ .replace(hour=0, minute=0, second=0, microsecond=0) \ .astimezone(pytz.utc)
但是......代码中存在一个比美学更大的问题:它会在切换到夏令时或从夏令时转换到错误的结果.
原因是日期时间构造函数既不replace()
考虑DST更改也不考虑.
例如:
>>> now = datetime(2012, 4, 1, 5, 0, 0, 0, tzinfo=pytz.timezone("Australia/Melbourne")) >>> print now 2012-04-01 05:00:00+10:00 >>> print now.replace(hour=0) 2012-04-01 00:00:00+10:00 # wrong! midnight was at 2012-04-01 00:00:00+11:00 >>> print datetime(2012, 3, 1, 0, 0, 0, 0, tzinfo=tz) 2012-03-01 00:00:00+10:00 # wrong again!
但是,tz.localize()
州的文件:
此方法应该用于构造localtimes,而不是将tzinfo参数传递给datetime构造函数.
因此,您的问题就像这样解决:
>>> import pytz >>> from datetime import datetime, date, time >>> tz = pytz.timezone("Australia/Melbourne") >>> the_date = date(2012, 4, 1) # use date.today() here >>> midnight_without_tzinfo = datetime.combine(the_date, time()) >>> print midnight_without_tzinfo 2012-04-01 00:00:00 >>> midnight_with_tzinfo = tz.localize(midnight_without_tzinfo) >>> print midnight_with_tzinfo 2012-04-01 00:00:00+11:00 >>> print midnight_with_tzinfo.astimezone(pytz.utc) 2012-03-31 13:00:00+00:00
但不保证1582年之前的日期.
@ hop的答案在夏令时(DST)过渡当天是错误的,例如2012年4月1日.要修复它tz.localize()
,可以使用:
tz = pytz.timezone("Australia/Melbourne") today = datetime.now(tz).date() midnight = tz.localize(datetime.combine(today, time(0, 0)), is_dst=None) utc_dt = midnight.astimezone(pytz.utc)
评论相同:
#!/usr/bin/env python from datetime import datetime, time import pytz # pip instal pytz tz = pytz.timezone("Australia/Melbourne") # choose timezone # 1. get correct date for the midnight using given timezone. today = datetime.now(tz).date() # 2. get midnight in the correct timezone (taking into account DST) #NOTE: tzinfo=None and tz.localize() # assert that there is no dst transition at midnight (`is_dst=None`) midnight = tz.localize(datetime.combine(today, time(0, 0)), is_dst=None) # 3. convert to UTC (no need to call `utc.normalize()` due to UTC has no # DST transitions) fmt = '%Y-%m-%d %H:%M:%S %Z%z' print midnight.astimezone(pytz.utc).strftime(fmt)