如何用Pandas计算跨年度日期区间内各月份的天数?
解决跨年度日期区间拆分各月份天数的问题
实现思路
- 先将
StartDate和EndDate转换为Pandas的datetime类型,便于日期计算 - 对每一行数据,生成从起始月份到结束月份的完整年月序列
- 针对每个年月,分场景计算实际天数:
- 起始月份:当月最后一天 - 起始日期 + 1天
- 结束月份:结束日期 - 当月第一天 + 1天
- 中间月份:直接取当月总天数
完整代码实现
import pandas as pd from pandas.tseries.offsets import MonthEnd, MonthBegin # 初始化示例数据 df = {'Id': ['1','2','3','4','5'], 'Item': ['A','B','C','D','E'], 'StartDate': ['2019-12-10', '2019-12-01', '2019-01-01', '2019-05-10', '2019-03-10'], 'EndDate': ['2020-01-30' ,'2020-02-02','2020-03-03','2020-03-03','2020-02-02'] } df = pd.DataFrame(df,columns= ['Id', 'Item','StartDate','EndDate']) # 转换日期列为datetime类型 df['StartDate'] = pd.to_datetime(df['StartDate']) df['EndDate'] = pd.to_datetime(df['EndDate']) # 定义函数拆分每个日期区间并计算每月天数 def split_date_range(row): start = row['StartDate'] end = row['EndDate'] # 生成所有涉及的年月(从起始月到结束月) months = pd.date_range(start=start.replace(day=1), end=end.replace(day=1), freq='MS') result = [] for month in months: month_start = month month_end = month + MonthEnd(1) # 确定该月的实际起止日期 actual_start = max(start, month_start) actual_end = min(end, month_end) # 计算天数 days = (actual_end - actual_start).days + 1 # 整理结果 result.append({ 'Id': row['Id'], 'Item': row['Item'], 'YearMonth': month.strftime('%Y-%m'), 'Days': days }) return pd.DataFrame(result) # 应用函数并合并最终结果 final_df = pd.concat(df.apply(split_date_range, axis=1).tolist(), ignore_index=True) print(final_df)
输出示例
运行代码后会得到如下结构的结果:
| Id | Item | YearMonth | Days |
|---|---|---|---|
| 1 | A | 2019-12 | 22 |
| 1 | A | 2020-01 | 30 |
| 2 | B | 2019-12 | 31 |
| 2 | B | 2020-01 | 31 |
| 2 | B | 2020-02 | 2 |
| 3 | C | 2019-01 | 31 |
| ... | ... | ... | ... |
关键细节说明
pd.date_range自动处理跨年度的月份生成,无需手动判断年份切换MonthBegin和MonthEnd工具类可以精准获取每个月的首尾日期,避免手动计算月末天数的误差- 通过
max和min锁定每个月的实际有效日期区间,确保天数计算完全匹配原日期范围
内容的提问来源于stack exchange,提问作者Diego Gonzalez Avalos
相关产品推荐
相关产品推荐

