如何基于给定StartDate和EndDate生成按月份拆分的Period时间段列表
C# 实现日期范围按自然月拆分
核心逻辑
- 首先校验输入合法性:若
startDate晚于endDate,直接返回空列表 - 如果两个日期属于同一个自然月,直接生成仅包含一条
Period记录的列表即可 - 跨月场景分三段处理:
- 首段:起始时间为
startDate,结束时间为startDate当月最后一天 - 中间段:遍历
startDate下一个月到endDate上一个月的所有自然月,每段为当月1日到当月最后一天的完整自然月 - 末段:起始时间为
endDate当月1日,结束时间为endDate
- 首段:起始时间为
注:代码中统一添加了
.Date处理,默认忽略日期的时分秒部分,仅按天维度计算,如有保留时分秒的需求可自行删除对应.Date调用。
代码实现
首先调整Period类为可读写属性(原定义为私有字段无法赋值):
public class Period { public DateTime FromDate { get; set; } public DateTime ToDate { get; set; } }
拆分逻辑实现:
public List<Period> SplitDateRangeByMonth(DateTime startDate, DateTime endDate) { List<Period> periodsList = new List<Period>(); // 输入合法性校验 if (startDate.Date > endDate.Date) { return periodsList; } // 同月场景直接返回 if (startDate.Year == endDate.Year && startDate.Month == endDate.Month) { periodsList.Add(new Period { FromDate = startDate.Date, ToDate = endDate.Date }); return periodsList; } // 处理首段 DateTime firstMonthEnd = new DateTime(startDate.Year, startDate.Month, 1) .AddMonths(1) .AddDays(-1) .Date; periodsList.Add(new Period { FromDate = startDate.Date, ToDate = firstMonthEnd }); // 处理中间完整自然月 DateTime current = startDate.AddMonths(1).Date; while (current.Year < endDate.Year || (current.Year == endDate.Year && current.Month < endDate.Month)) { DateTime currentMonthEnd = new DateTime(current.Year, current.Month, 1) .AddMonths(1) .AddDays(-1) .Date; periodsList.Add(new Period { FromDate = new DateTime(current.Year, current.Month, 1).Date, ToDate = currentMonthEnd }); current = current.AddMonths(1); } // 处理末段 periodsList.Add(new Period { FromDate = new DateTime(endDate.Year, endDate.Month, 1).Date, ToDate = endDate.Date }); return periodsList; }
调用示例
DateTime startDate = new DateTime(2021, 2, 15); DateTime endDate = new DateTime(2021, 8, 18); List<Period> periodsList = SplitDateRangeByMonth(startDate, endDate);
执行后得到的periodsList与你给出的示例完全一致。
内容的提问来源于stack exchange,提问作者Cloud-Lover
相关产品推荐
相关产品推荐

