如何获得“午夜”的UTC时间对于给定的时区?
题
我可以想出用于现在的最好的是这个畸形:
>>> 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。
我不只是现在使用()或本地时间(),因为这将使用服务器的时区,而不是用户的时区。
我不禁感慨,我失去了一些东西,什么想法?
解决方案
我想,如果你不喜欢这样,你可以刮掉一些方法调用:
>>> 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之前,虽然。
其他提示
@跳的回答是错误的过渡,从夏令时(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)
设置TZ环境变量的改变是什么时区Python的日期和时间功能一起工作。
>>> time.gmtime()
(2008, 12, 17, 1, 16, 46, 2, 352, 0)
>>> time.localtime()
(2008, 12, 16, 20, 16, 47, 1, 351, 0)
>>> os.environ['TZ']='Australia/Melbourne'
>>> time.localtime()
(2008, 12, 17, 12, 16, 53, 2, 352, 1)
每个时区的数,例如,美国/中心= -6。这被定义为在从UTC小时的偏移。由于0000是午夜,你可以简单地使用这个偏移找到任何时区的时间,当它是午夜UTC。要访问,我相信你可以使用
time.timezone
根据 Python的文档,time.timezone实际上给出的负值这个号码:
time.timezone
本地(非DST)时区的偏移量,以秒为西部UTC的。
(在大多数西欧,积极在美国,零在英国的负)
所以,你会简单地使用该号码为以小时的时间,如果是正的(即,如果它是在芝加哥(其具有6时区值午夜),那么它的6000 =上午06时UTC)。
如果数是负的,从24。例如减法,柏林会给-1,所以24 - 1 => 2300 =下午11点
这是与dateutil.tz比pytz更直截了当:
>>>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
在 tzinfo文档建议dateutil.tz因为Python 3.6。从dateutil.tz的tzinfo对象有像DST异常没有问题,无需pytz的本地化功能。从user3850使用例如:
>>> 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