如何获取给定时区的“午夜”的UTC时间?
如何获取给定时区的“午夜”的UTC时间?
我现在能想到的最好的解决方案是这个怪物代码:\n
>>> 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)
\n换句话说,用英语来说,获取当前时间(以UTC为准),将其转换为其他时区,将时间设置为午夜,然后再转换回UTC。\n我不仅仅使用now()或localtime(),因为那会使用服务器的时区,而不是用户的时区。\n我感觉我可能漏掉了什么,有什么建议吗?
问题的出现原因:
用户想要获取给定时区的“午夜”的UTC时间。
解决方法:
使用dateutil.tz库比pytz库更加简单明了。以下是使用dateutil.tz库的代码示例:
>>> import datetime >>> import dateutil.tz >>> midnight = (datetime.datetime .now(dateutil.tz.gettz('Australia/Melbourne')) .replace(hour=0, minute=0, second=0, microsecond=0) .astimezone(dateutil.tz.tzutc())) >>> print(midnight) 2019-04-26 14:00:00+00:00
在Python 3.6及以上版本中,tzinfo文档推荐使用dateutil.tz。dateutil.tz库的tzinfo对象在处理DST等异常情况时没有pytz库中所需的本地化功能。以下是用户3850的示例代码:
>>> now = (datetime.datetime(2012, 4, 1, 5, tzinfo=dateutil.tz.gettz('Australia/Melbourne'))) >>> print(now.replace(hour=0).astimezone(dateutil.tz.tzutc())) 2012-03-31 13:00:00+00:00
问题的出现原因是在夏令时转换的那一天,即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) # 将当地时间转换为UTC时间
同样的代码带有注释:
#!/usr/bin/env python from datetime import datetime, time import pytz # 需要安装pytz库 tz = pytz.timezone("Australia/Melbourne") # 选择时区 # 1. 使用给定时区获取正确的日期以获取午夜时间。 today = datetime.now(tz).date() # 2. 在正确的时区获取午夜时间(考虑夏令时)。 # 注意:tzinfo=None和tz.localize()确保在午夜时没有夏令时转换(`is_dst=None`)。 midnight = tz.localize(datetime.combine(today, time(0, 0)), is_dst=None) # 3. 转换为UTC时间(由于UTC没有夏令时转换,所以不需要调用`utc.normalize()`)。 fmt = '%Y-%m-%d %H:%M:%S %Z%z' print midnight.astimezone(pytz.utc).strftime(fmt)
有些困惑。夏令时切换发生在凌晨3点,所以当天的午夜时间应该仍然是14:00 UTC,而不是13:00 UTC,不是吗?
:将2012年3月31日13:00 UTC转换为墨尔本时区并自行查看(它仍然是+11时区(夏令时),而不是+10时区(标准时间))。
time()
与time(0, 0)
是相同的,只是更简洁。
问题的原因是在给定时区中获取"午夜"的UTC时间。然而,代码中存在一个问题,即在夏令时切换的那天,代码将给出错误的结果。原因是datetime构造函数和replace()方法都没有考虑夏令时的变化。
解决方法是使用tz.localize()方法来构造本地时间。代码如下:
import pytz from datetime import datetime, date, time tz = pytz.timezone("Australia/Melbourne") the_date = date(2012, 4, 1) midnight_without_tzinfo = datetime.combine(the_date, time()) midnight_with_tzinfo = tz.localize(midnight_without_tzinfo) utc_time = midnight_with_tzinfo.astimezone(pytz.utc) print(utc_time)
需要注意的是,这个方法在1582年之前的日期上没有保证。另外,代码中的".localize()/.normalize()"可能是必需的。