C#日期序列输出含结束日期异常:起始日大于结束日时丢失数据
问题分析与解决方案
看起来你遇到的核心问题是:循环条件基于完整日期的大小比较,导致当起始日期的日部分大于结束日期的日部分时,结束日期所在的月份被遗漏。
为什么会出现这个问题?
你的原循环是从EndDate开始,通过i > StartDate的条件控制遍历,但这个判断是基于完整的年月日。比如第一个例子里,StartDate=06/28/2019,EndDate=09/27/2019:
- 当往回遍历月份时(假设
AddMonths参数是-1,否则你的输出逻辑无法解释),最后一次循环的i会变成06/27/2019,此时06/27 > 06/28不成立,循环停止。但你需要处理的是6月到9月的所有月份,而非日期的大小,这种基于完整日期的判断就会漏掉9月的计算。
修复方案:基于月份范围遍历
我们可以把月份转换成「年份×12+月份」的数字序号,这样就能直接遍历起始到结束的所有月份,完全不受日部分的影响。
修改后的代码如下:
static void Main(string[] args) { var StartDate = DateTime.Parse("06/28/2019"); var EndDate = DateTime.Parse("09/27/2019"); // 把月份转成数字序号,方便跨年份遍历 int startMonthIndex = StartDate.Year * 12 + StartDate.Month; int endMonthIndex = EndDate.Year * 12 + EndDate.Month; // 遍历每个需要处理的月份 for (int currentMonthIndex = startMonthIndex; currentMonthIndex <= endMonthIndex; currentMonthIndex++) { // 从序号还原年份和月份 int year = currentMonthIndex / 12; int month = currentMonthIndex % 12; // 处理12月的特殊情况(12%12=0) if (month == 0) { year--; month = 12; } // 你原来的第四个周一计算逻辑 var firstDayOfMonth = new DateTime(year, month, 1); int dayDifference = (int)DayOfWeek.Monday - (int)firstDayOfMonth.DayOfWeek; int addDays = dayDifference > 0 ? 21 : 28; var fourthMonday = firstDayOfMonth.AddDays(dayDifference + addDays); // 如果你需要确保输出的日期在StartDate和EndDate之间,可以加这个判断 // 不需要的话直接注释掉即可 if (fourthMonday >= StartDate && fourthMonday <= EndDate) { Console.WriteLine(fourthMonday); } } }
代码说明
- 月份序号遍历:通过
年份×12+月份把每个月份转换成唯一的数字,不管跨不跨年,都能连续遍历,彻底避免日部分的干扰。 - 日期范围过滤:可选的
if判断可以确保只输出在StartDate和EndDate之间的第四个周一,如果你想输出所有月份的第四个周一(哪怕早于StartDate),直接去掉这个判断即可。 - 原逻辑保留:你原来计算第四个周一的逻辑完全保留,只修改了遍历的方式。
测试你第一个例子时,去掉过滤判断会输出6/24/2019 7/22/2019 8/26/2019 9/23/2019,符合预期;保留过滤判断则会跳过6月的日期(因为6/24早于6/28)。
内容的提问来源于stack exchange,提问作者user2061998




