首页 > 解决方案 > `pytz.localize()` 四舍五入到最接近的现有小时(在 DST 跳跃的情况下)

问题描述

基本上,我得到了:

tz = pytz.timezone('US/Eastern')
dt = datetime.datetime(2019, 03, 10, 02, 30)

我想dt在删除不存在的小时的同时本地化到时区。

如果我这样做tz.normalize(tz.localize(dt)),我会得到

datetime.datetime(2019, 3, 10, 3, 30, tzinfo=<DstTzInfo 'US/Eastern' EDT-1 day, 20:00:00 DST>)

我想

datetime.datetime(2019, 3, 10, 3, 00, tzinfo=<DstTzInfo 'US/Eastern' EDT-1 day, 20:00:00 DST>)

(使用 03:00 而不是 03:30,因为它更接近挂钟 02:30)。

用例:我得到了一个挂钟时间列表(其中一个恰好是 02:30)、2019 年 3 月 10 日的日期时间和美国/东部时区。

我想使用 03:00(实际上是 DST 飞跃后的时间)构建特定日期时间和时区中的时间戳,而不是在我将时间戳与日期时间结合并对其进行本地化时将变为无效的任何挂起时间。这样做是为了自动将一些与挂钟时间相关的约会列表复制到另一天。

标签: pythonpytz

解决方案


def localize_and_round_datetime(dt, tz):
    """
    Similar to tz.normalize(tz.localize(dt)), but rounds any time in non-existing hour to the time right after it.
    """
    result = tz.normalize(tz.localize(dt))
    if result.replace(tzinfo=None) == dt:
        return result

    # DT belongs to the leap hour. find the datetime right after leap
    # see: DstTzInfo.localize()
    tzinfo_dst_idx = bisect_right(tz._utc_transition_times, dt)
    new_tz = tz._utc_transition_times[tzinfo_dst_idx]
    return pytz.UTC.localize(new_tz).astimezone(tz)

似乎工作。


推荐阅读