给定一个 UTC 时间,获取指定时区的午夜

Given a UTC time, get a specified timezone's midnight

请注意,这与 this question 完全 不同。该问题假设您想要的时间是 "now",这与任意时间点不同。

我有一个 UTC、感知、日期时间对象,将其命名为 point_in_time(例如 datetime(2017, 3, 12, 16, tzinfo=tz.tzutc()))。

我有一个时区,称它为 location(例如 'US/Pacific'),因为我关心 它所在的位置,但它的时间与 UTC 有偏差全年可能会因夏令时等因素而发生变化。

我想
1) 如果我站在 location,
获取 point_in_time 的日期 2) 如果我站在 location.

,则得到那个日期的午夜

===

我试着简单地使用 .astimezone(timezone('US/Pacific')) 然后 .replace(hours=0, ...) 移动到午夜,但是你可能会注意到我的示例 point_in_time,那个日期的午夜在另一个夏令时开关的一侧!

结果是我得到的是代表UTC的时间datetime(2017, 3, 12, 7),而不是代表UTC的时间datetime(2017, 3, 12, 8),这才是真正的午夜。

编辑:
我实际上在想我的问题和相关问题之间的区别在于我正在寻找过去最近的午夜。那个问题的答案似乎可以给出一个可能是过去或未来的午夜,也许?

"US/Pacific" 等命名时区根据定义可识别夏令时。如果您希望使用 GMT 的固定非夏令时感知偏移量,您可以使用时区 "Etc/GMT+*",其中 * 是所需的偏移量。例如,对于美国太平洋标准时间,您将使用 "Etc/GMT+8":

import pandas as pd
point_in_time = pd.to_datetime('2017-03-12 16:00:00').tz_localize('UTC')

# not what you want
local_time = point_in_time.tz_convert("US/Pacific")
(local_time - pd.Timedelta(hours=local_time.hour)).tz_convert('UTC')
# Timestamp('2017-03-12 07:00:00+0000', tz='UTC')

# what you want
local_time = point_in_time.tz_convert("Etc/GMT+8")
(local_time - pd.Timedelta(hours=local_time.hour)).tz_convert('UTC')
# Timestamp('2017-03-12 08:00:00+0000', tz='UTC')

有关详细信息,请参阅 http://pvlib-python.readthedocs.io/en/latest/timetimezones.html 上的文档。

编辑现在我想起来了,太平洋标准时间午夜将始终是世界标准时间上午 8 点,因此您可以将其简化为

if point_in_time.hour >=8:
    local_midnight = point_in_time - point_in_time.hour + 8
else:
    local_midnight = point_in_time - point_in_time.hour - 16

您的示例突出了在本地时区进行日期时间运算的危险。

您可能可以使用 pytz 的 normalize() 函数来实现此目的,但这是我想到的方法:

point_in_time = datetime(2017, 3, 12, 16, tzinfo=pytz.utc)
pacific = pytz.timezone("US/Pacific")
pacific_time = point_in_time.astimezone(pacific)
pacific_midnight_naive = pacific_time.replace(hour=0, tzinfo=None)
pacific_midnight_aware = pacific.localize(pacific_midnight_naive)
pacific_midnight_aware.astimezone(pytz.utc)  # datetime(2017, 3, 12, 8)

换句话说,你先转换成太平洋时间来算出正确的日期;然后您从该日期的午夜再次转换以获得正确的当地时间。