【发布时间】:2021-11-19 13:23:37
【问题描述】:
我正在尝试将任意输入 pd.Timestamp 移回正确的起始偏移量,除非它已经在偏移量上。
以下代码适用于BusinessMonthEnd、MonthEnd、MonthStart 等:
import pandas as pd
from pandas.tseries.offsets import *
def to_start(t: pd.Timestamp, freq: pd.DateOffset) -> pd.Timestamp:
return freq.rollback(t)
assert to_start(pd.to_datetime("2021-09-27"), MonthEnd()) == pd.to_datetime("2021-08-31")
assert to_start(pd.to_datetime("2021-09-27"), MonthBegin()) == pd.to_datetime("2021-08-31")
assert to_start(pd.to_datetime("2021-08-27"), BMonthEnd()) == pd.to_datetime("2021-07-30")
assert to_start(pd.to_datetime("2021-08-27"), YearBegin()) == pd.to_datetime("2021-01-01")
assert to_start(pd.to_datetime("2021-08-27"), BYearBegin()) == pd.to_datetime("2021-01-01")
# also it works nicely with holiday calendars
from pandas.tseries.holiday import USFederalHolidayCalendar
us_fed_biz_days = CustomBusinessDay(calendar=USFederalHolidayCalendar())
memorial_day = pd.to_datetime("2021-05-31")
the_friday_before_memorial_day = pd.to_datetime("2021-05-28")
assert to_start(memorial_day, us_fed_biz_days) == the_friday_before_memorial_day
但是(这让我发疯)它似乎不适用于Day、BusinessDay、Week、Hour 等:
assert to_start(pd.to_datetime("2021-08-27 05:00"), Day()) == pd.to_datetime("2021-08-27")
assert to_start(pd.to_datetime("2021-08-27 05:00"), BDay()) == pd.to_datetime("2021-08-27")
assert to_start(pd.to_datetime("2021-08-27 05:15"), Hour()) == pd.to_datetime("2021-08-27 05:00")
assert to_start(pd.to_datetime("2021-08-26"), pd.tseries.frequencies.to_offset("W-MON")) == pd.to_datetime("2021-08-24")
我也试过这个:
def to_start(t: pd.Timestamp, freq: pd.DateOffset) -> pd.Timestamp:
return pd.Period(t, freq=freq).start_time
具有讽刺意味的是,它适用于第二组断言但不适用于第一组?
我对上述断言的期望不是不合理吗?如果是,请问我错过了什么?
【问题讨论】:
-
如果您查看 source code 中的函数,您会发现在比较中使用哪种偏移量会有所不同 - 在示例的上半部分,您有可变的偏移量(与给定的日期/时间相比),在下部,偏移量是固定的(BDay 介于两者之间)。
-
我编辑了问题以删除不需要的
is_on_offset()调用。我还添加了另一个假期用例。
标签: python pandas datetime offset datetimeoffset