我如何获得“午夜"的UTC时间?对于给定的时区? [英] How do I get the UTC time of "midnight" for a given timezone?

查看:29
本文介绍了我如何获得“午夜"的UTC时间?对于给定的时区?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我现在能想到的最好的就是这个怪物:

<预><代码>>>>日期时间.utcnow() ... .replace(tzinfo=pytz.UTC) ... .astimezone(pytz.timezone("澳大利亚/墨尔本")) ... .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() 因为它们会使用服务器的时区,而不是用户的时区.

我不禁觉得我错过了什么,有什么想法吗?

解决方案

我认为如果你这样做,你可以减少一些方法调用:

<预><代码>>>>从日期时间导入日期时间>>>datetime.now(pytz.timezone("澳大利亚/墨尔本")) .replace(小时=0, 分钟=0, 秒=0, 微秒=0) .astimezone(pytz.utc)

但是……在您的代码中有一个比美学更重要的问题:它会在切换到夏令时或从夏令时切换的那天给出错误的结果.

这样做的原因是日期时间构造函数和 replace() 都没有考虑 DST 更改.

例如:

<预><代码>>>>现在 = 日期时间(2012, 4, 1, 5, 0, 0, 0, tzinfo=pytz.timezone("澳大利亚/墨尔本"))>>>现在打印2012-04-01 05:00:00+10:00>>>立即打印.replace(小时=0)2012-04-01 00:00:00+10:00 # 错了!午夜是在 2012-04-01 00:00:00+11:00>>>打印日期时间(2012, 3, 1, 0, 0, 0, 0, tzinfo=tz)2012-03-01 00:00:00+10:00 # 又错了!

但是,tz.localize() 的文档指出:

<块引用>

这个方法应该用于构造localtimes,而不是而不是将 tzinfo 参数传递给日期时间构造函数.

这样,你的问题就这样解决了:

<预><代码>>>>进口pytz>>>从日期时间导入日期时间,日期,时间>>>tz = pytz.timezone("澳大利亚/墨尔本")>>>the_date = date(2012, 4, 1) # 在这里使用 date.today()>>>midnight_without_tzinfo = datetime.combine(the_date, time())>>>打印midnight_without_tzinfo2012-04-01 00:00:00>>>midnight_with_tzinfo = tz.localize(midnight_without_tzinfo)>>>打印midnight_with_tzinfo2012-04-01 00:00:00+11:00>>>打印midnight_with_tzinfo.astimezone(pytz.utc)2012-03-31 13:00:00+00:00

但不能保证 1582 年之前的日期.

The best I can come up with for now is this monstrosity:

>>> 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)

I.e., in English, get the current time (in UTC), convert it to some other timezone, set the time to midnight, then convert back to UTC.

I'm not just using now() or localtime() as that would use the server's timezone, not the user's timezone.

I can't help feeling I'm missing something, any ideas?

解决方案

I think you can shave off a few method calls if you do it like this:

>>> from datetime import datetime
>>> datetime.now(pytz.timezone("Australia/Melbourne")) 
            .replace(hour=0, minute=0, second=0, microsecond=0) 
            .astimezone(pytz.utc)

BUT… there is a bigger problem than aesthetics in your code: it will give the wrong result on the day of the switch to or from Daylight Saving Time.

The reason for this is that neither the datetime constructors nor replace() take DST changes into account.

For example:

>>> 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!

However, the documentation for tz.localize() states:

This method should be used to construct localtimes, rather than passing a tzinfo argument to a datetime constructor.

Thus, your problem is solved like so:

>>> 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

No guarantees for dates before 1582, though.

这篇关于我如何获得“午夜"的UTC时间?对于给定的时区?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆