为何pd.date_range()的终止包容性会随频率参数不同而变化?
为什么pd.date_range(freq='M')不包含指定的结束月份?
核心原因很简单:pd.date_range和pd.period_range的本质完全不同——前者生成单个时间点(Timestamp)的序列,后者生成时间段(Period)的序列,两者的范围判定规则自然不一样。
1. 日频率(freq='D')的一致性
当使用日频率时,两者表现一致很好理解:
pd.date_range(start='1999-08-01', end='2000-07-01', freq='D')生成的是从起始日到结束日的每一天的时间戳,最后一个时间戳就是2000-07-01,完全符合终止包含的预期。pd.period_range(start='1999-08-01', end='2000-07-01', freq='D')生成的是每一天对应的时间段(比如2000-07-01代表当天一整天),这个时间段在指定范围内,所以也会被包含。
2. 月频率(freq='M')的差异拆解
先看pd.date_range(start='1999-08', end='2000-07', freq='M')
- 当
freq='M'时,date_range生成的是每个月最后一天的时间戳。 - 你传入的
end='2000-07'会被pandas自动解析为2000-07-01 00:00:00这个具体时间点。 - 7月的最后一天是
2000-07-31,这个时间戳明显晚于2000-07-01,超出了end的范围,所以不会被纳入结果。最终生成的序列是从1999-08-31到2000-06-30,共11个时间戳。
再看pd.period_range(start='1999-08', end='2000-07', freq='M')
- 当
freq='M'时,period_range生成的是完整月度的时间段(比如1999-08代表1999年8月1日到8月31日的整个区间)。 - 这里的
end='2000-07'指的是「2000年7月这个完整时间段」,它完全落在起始时间段到结束时间段的范围内,所以会被包含。最终生成的序列是从1999-08到2000-07,共12个月度时间段。
一句话总结
date_range判断的是「生成的时间戳是否≤指定的end时间点」,而period_range判断的是「生成的时间段是否落在start到end的区间内(或等于end对应的时间段)」——这就是两者表现差异的核心原因。
内容的提问来源于stack exchange,提问作者NovicePatience
相关产品推荐
相关产品推荐

