验证排除周末的员工请假天数统计逻辑,修复求和结果错误
按年月拆分统计员工请假总天数(排除周末)的计算错误修复
问题说明
需要按年月维度统计所有员工的请假总天数,统计规则要求排除周末,但当前代码的计算结果存在错误。
现有代码
核心计算方法
public double CalculateLeaveDaysForPeriod(List<EmployeeInfoDto> staffMembers, DateTime periodStart, DateTime periodEnd) { double totalLeaveDays = 0; foreach (var staffMember in staffMembers) { foreach (var leaveRequest in staffMember.LeaveRequests) { DateTime leaveStartDate = leaveRequest.StartDate; DateTime leaveEndDate = leaveRequest.EndDate; DateTime validStartDate = leaveStartDate > periodStart ? leaveStartDate : periodStart; DateTime validEndDate = leaveEndDate < periodEnd ? leaveEndDate : periodEnd; if (validStartDate < validEndDate) { for (DateTime currentDay = validStartDate; currentDay <= validEndDate; currentDay = currentDay.AddDays(1)) { if (currentDay.DayOfWeek != DayOfWeek.Saturday && currentDay.DayOfWeek != DayOfWeek.Sunday) { totalLeaveDays++; } } } } } return totalLeaveDays; }
年月维度统计方法
public double GetLeaveDaysForCurrentMonth(List<EmployeeInfoDto> employees) { var currentDate = DateTime.Now; var startOfMonth = new DateTime(currentDate.Year, currentDate.Month, 1); var endOfMonth = startOfMonth.AddMonths(1).AddDays(-1); return GetLeaveDaysForTimePeriod(employees, startOfMonth, endOfMonth); } public double GetLeaveDaysForCurrentYear(List<EmployeeInfoDto> employees) { var currentDate = DateTime.Now; var startOfYear = new DateTime(currentDate.Year, 1, 1); var endOfYear = new DateTime(currentDate.Year, 12, 31); return GetLeaveDaysForTimePeriod(employees, startOfYear, endOfYear); }
员工请假数据示例(JSON)
[ { "leaveRequests": [ { "startDate": "2025-01-07T23:00:00Z", "endDate": "2025-01-09T23:00:00Z" } ] }, { "leaveRequests": [ { "startDate": "2025-01-05T23:00:00Z", "endDate": "2025-01-17T23:00:00Z" } ] }, { "leaveRequests": [ { "startDate": "2025-01-08T23:00:00Z", "endDate": "2025-01-23T23:00:00Z" } ] } ]
错误原因分析
- 方法调用不匹配:
GetLeaveDaysForCurrentMonth和GetLeaveDaysForCurrentYear调用了不存在的GetLeaveDaysForTimePeriod方法,实际核心方法是CalculateLeaveDaysForPeriod,直接导致编译错误或执行异常。 - 时区与时间干扰:JSON中的日期为UTC格式(带
Z后缀),但代码直接用DateTime处理未做时区转换,且保留时间部分,会导致日期边界判断错误(例如2025-01-07T23:00:00Z转换为本地时间可能变为1月8日)。 - 日期范围判断逻辑缺陷:
if (validStartDate < validEndDate)会跳过请假起始与结束为同一天的场景,导致当天请假天数未被统计。 - 循环边界误差:使用带时间的
DateTime进行循环遍历,可能因时间部分导致重复统计或漏统计。
修复后的代码
修正后的核心计算方法
public double CalculateLeaveDaysForPeriod(List<EmployeeInfoDto> staffMembers, DateTime periodStart, DateTime periodEnd) { double totalLeaveDays = 0; // 统一转换为UTC时间,对齐JSON数据的时区 DateTime utcPeriodStart = periodStart.ToUniversalTime(); DateTime utcPeriodEnd = periodEnd.ToUniversalTime(); foreach (var staffMember in staffMembers) { foreach (var leaveRequest in staffMember.LeaveRequests) { // 将请假日期转换为UTC时间 DateTime leaveStartUtc = leaveRequest.StartDate.ToUniversalTime(); DateTime leaveEndUtc = leaveRequest.EndDate.ToUniversalTime(); // 使用DateOnly忽略时间部分,专注日期计算 DateOnly leaveStart = DateOnly.FromDateTime(leaveStartUtc); DateOnly leaveEnd = DateOnly.FromDateTime(leaveEndUtc); DateOnly periodStartDate = DateOnly.FromDateTime(utcPeriodStart); DateOnly periodEndDate = DateOnly.FromDateTime(utcPeriodEnd); // 确定有效统计范围 DateOnly actualStart = leaveStart > periodStartDate ? leaveStart : periodStartDate; DateOnly actualEnd = leaveEnd < periodEndDate ? leaveEnd : periodEndDate; // 覆盖当天请假的场景 if (actualStart <= actualEnd) { for (DateOnly currentDay = actualStart; currentDay <= actualEnd; currentDay = currentDay.AddDays(1)) { if (currentDay.DayOfWeek != DayOfWeek.Saturday && currentDay.DayOfWeek != DayOfWeek.Sunday) { totalLeaveDays++; } } } } } return totalLeaveDays; }
修正后的年月统计方法
public double GetLeaveDaysForCurrentMonth(List<EmployeeInfoDto> employees) { var currentDate = DateTime.Now; var startOfMonth = new DateTime(currentDate.Year, currentDate.Month, 1); var endOfMonth = startOfMonth.AddMonths(1).AddDays(-1); return CalculateLeaveDaysForPeriod(employees, startOfMonth, endOfMonth); } public double GetLeaveDaysForCurrentYear(List<EmployeeInfoDto> employees) { var currentDate = DateTime.Now; var startOfYear = new DateTime(currentDate.Year, 1, 1); var endOfYear = new DateTime(currentDate.Year, 12, 31); return CalculateLeaveDaysForPeriod(employees, startOfYear, endOfYear); }
修复要点说明
- 统一使用UTC时间处理,解决JSON数据与本地时间的时区偏差问题;
- 采用
DateOnly类型(.NET 6及以上版本支持),彻底消除时间部分对日期统计的干扰; - 修正方法调用名称,确保调用正确的核心计算逻辑;
- 调整日期范围判断条件为
actualStart <= actualEnd,覆盖当天请假的统计场景; - 循环遍历使用
DateOnly,保证日期判断的准确性。
内容的提问来源于stack exchange,提问作者Kafkaa
相关产品推荐
相关产品推荐

