如何找到时区的下一个早上7点 [英] How do I find the next 7am in a timezone

查看:90
本文介绍了如何找到时区的下一个早上7点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

current_datetime = datetime.now(tz)
next_hour = datetime(current_datetime.year, current_datetime.month, current_datetime.day, 7, 0, 0, 0, tz)
timedelta_until_next_hour = next_hour - current_datetime
if timedelta_until_next_hour.total_seconds() < 0:
    timedelta_until_next_hour += timedelta(days=1)
return timedelta_until_next_hour.total_seconds()

我正在尝试查找下一次是本地时区的上午7点,并返回直到该时间的秒数。

I'm trying to find the next time it's 7am for a local timezone and return the number of seconds until that.

我有一些夏令时时间问题。例如:美国/纽约 current_datetime 的utcoffset为-4小时
next_hour 的偏移量为-5小时,因此两者的减法为一个小时

I'm having some daylight savings time issues. For Example: America/New_York current_datetime has a utcoffset of -4 hours Whereas next_hour has an offset of -5 hours, so the subtraction of the two is off by an hour

推荐答案

查找下一个上午7点



使用 python-dateutil relativedelta 模块

from dateutil.relativedelta import relativedelta
def next_7am(dt):
    relative_days = (dt.hour >= 7)
    absolute_kwargs = dict(hour=7, minute=0, second=0, microsecond=0)
    return dt + relativedelta(days=relative_days, **absolute_kwargs)

它的工作方式是 relativedelta 需要绝对参数(以单数表示,例如 month year day )和 relative 参数(以复数形式表示,例如个月)。如果在 datetime 中添加 relativedelta 对象,它将替换绝对值。 datetime ,然后添加相对值,因此我在上面所做的是指定 relative_days 如果已经是早上7点,则应该是 1 ,否则应该是0,并且绝对参数说将时间替换为7 AM。将其添加到您的日期时间,它将为您提供下一个上午7点。

The way it works is that relativedelta takes absolute arguments (denoted by being in the singular, e.g. month, year, day) and relative arguments (denoted by being in the plural, e.g. months, years, days). If you add a relativedelta object to a datetime, it will replace absolute values in the datetime, then add the relative values, so what I've done above is specify that relative_days should be 1 if it's already 7am, otherwise it should be 0, and the absolute arguments say "replace the time with 7 AM". Add that to your datetime and it will give you the next 7am.

下一个步骤取决于您的时区使用什么。如果您使用的是 dateutil 时区,则可以使用上面定义的函数:

The next step depends on what you are using for your time zone. If you are using a dateutil time zone, then you can just use the function defined above:

dt_next_7am = next_7am(dt)

如果您使用的是 pytz 时区,您应该将其剥离并作为原始日期时间进行计算,然后重新定位时区,如下所示:

If you are using a pytz timezone, you should strip it off and do the calculation as a naive date-time, then re-localize the time zone, as below:

dt_next_7am = tz.localize(next_7am(dt.replace(tzinfo=None)))

如果要获取两次之间的绝对小时数,则应使用UTC进行算术运算。

If you want to get the absolute number of hours between those two times, you should do the arithmetic in UTC:

time_between = dt_next_7am.astimezone(tz=UTC) - dt.astimezone(tz=UTC)

其中 UTC 被定义为 dateutil.tz.tzutc() pytz.UTC 或等价货币。

Where UTC has been defined as either dateutil.tz.tzutc() or pytz.UTC or equivalent.

这是使用 dateutil 的示例(结果在注释中):

Here is an example using dateutil (with the result in the comment):

from datetime import datetime
from dateutil.tz import gettz, tzutc

LA = gettz('America/Los_Angeles')
dt = datetime(2011, 11, 5, 12, 30, tzinfo=LA)
dt7 = next_7am(dt)

print(dt7.astimezone(tzutc()) - dt.astimezone(tzutc()))  # 19:30:00

以及显示错误和正确方法的示例为此,请使用 pytz

And an example showing the wrong and right way to do this with pytz:

from datetime import datetime
import pytz
LA = pytz.timezone('America/Los_Angeles')
UTC = pytz.UTC

dt = LA.localize(datetime(2011, 11, 5, 12, 30))
dt7_bad = next_7am(dt)      # pytz won't like this
dt7_good = LA.localize(next_7am(dt.replace(tzinfo=None)))

dt_utc = dt.astimezone(pytz.UTC)
print(dt7_bad.astimezone(pytz.UTC) - dt_utc)   # 18:30:00 (Wrong)
print(dt7_good.astimezone(pytz.UTC) - dt_utc)  # 19:30:00 (Right)



模棱两可/不存在



如果以下列表(截至2016年4月)处理某些区域中的某些日期,尤其是那些会导致时间不明确的日期:

Ambiguous / Non-existent 7 AM

If you are dealing with certain dates in certain zones, specifically those that would result in an ambiguous time are on the following list (as of April 2016):

1901-12-13 07:00:00 (/Pacific/Fakaofo)
1901-12-14 07:00:00 (/Asia/Kamchatka)
1901-12-14 07:00:00 (/Asia/Ust-Nera)
1901-12-14 07:00:00 (/Pacific/Bougainville)
1901-12-14 07:00:00 (/Pacific/Kosrae)
1901-12-14 07:00:00 (/Pacific/Majuro)
1917-03-25 07:00:00 (/Antarctica/Macquarie)
1918-03-31 07:00:00 (/EST5EDT)
1919-03-31 07:00:00 (/Antarctica/Macquarie)
1952-01-13 07:00:00 (/Antarctica/DumontDUrville)
1954-02-13 07:00:00 (/Antarctica/Mawson)
1957-01-13 07:00:00 (/Antarctica/Davis)
1969-01-01 07:00:00 (/Antarctica/Casey)
1969-02-01 07:00:00 (/Antarctica/Davis)
1969-09-29 07:00:00 (/Kwajalein)
1969-09-29 07:00:00 (/Pacific/Kwajalein)
1979-09-30 07:00:00 (/Pacific/Enderbury)
1979-09-30 07:00:00 (/Pacific/Kiritimati)
2009-10-18 07:00:00 (/Antarctica/Casey)
2011-09-23 07:00:00 (/Pacific/Apia)
2011-10-28 07:00:00 (/Antarctica/Casey)

然后得出的7AM值将是模棱两可或不存在。如果要处理这些极端情况,请参阅此答案。可能值得注意的是,在实施 PEP495 之后,处理的模棱两可

Then the resulting 7AM value will be either ambiguous or non-existent. If you want to handle these edge cases, see this answer. It is probably worth noting that after PEP495 has been implemented, dealing with ambiguous times will probably be handled slightly differently.

使用 python-dateutil pytz 区域的重复规则和方法的> rrule 模块(请注意,该模块将与非 pytz一起使用区域,但无法正确解决模糊/不存在的时间):

An alternative implementation using python-dateutil's rrule module for generating recurrence rules and approach with pytz zones is below (note that this will work with non-pytz zones, but it will not resolve ambiguious/non-existent times properly):

from datetime import datetime
from dateutil import rrule
import pytz

def next_real_7am(dt):
    tzi = dt.tzinfo

    dt_naive = dt.replace(tzinfo=None)
    rr = rrule.rrule(freq=rrule.DAILY, byhour=7, dtstart=dt_naive)

    for ndt in rr:
        localize = getattr(tzi, 'localize', None)
        if tzi is not None and localize is not None:
            try:
                ndt = localize(ndt, is_dst=None)
            except pytz.AmbiguousTimeError:
                return min([localize(ndt, is_dst=True),
                            localize(ndt, is_dst=False)])
            except pytz.NonExistentTimeError:
                continue
        else:
            ndt = ndt.replace(tzinfo=tzi)

        return ndt

KWA = pytz.timezone('Pacific/Kwajalein')

dtstart = KWA.localize(datetime(1969, 9, 29, 18))
dt7 = next_real_7am(dtstart)

print(dt7.tzname())         # Should be MHT, before the transition

dtstart = KWA.localize(datetime(1993, 8, 19, 18))  # There was no 8/20 in this zone
dt7 = next_real_7am(dtstart)
print(dt7)                  # Should be 1993-8-21 07:00:00

这篇关于如何找到时区的下一个早上7点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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