You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

验证排除周末的员工请假天数统计逻辑,修复求和结果错误

按年月拆分统计员工请假总天数(排除周末)的计算错误修复

问题说明

需要按年月维度统计所有员工的请假总天数,统计规则要求排除周末,但当前代码的计算结果存在错误。

现有代码

核心计算方法

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"
      }
    ]
  }
]

错误原因分析

  1. 方法调用不匹配:GetLeaveDaysForCurrentMonth和GetLeaveDaysForCurrentYear调用了不存在的GetLeaveDaysForTimePeriod方法,实际核心方法是CalculateLeaveDaysForPeriod,直接导致编译错误或执行异常。
  2. 时区与时间干扰:JSON中的日期为UTC格式(带Z后缀),但代码直接用DateTime处理未做时区转换,且保留时间部分,会导致日期边界判断错误(例如2025-01-07T23:00:00Z转换为本地时间可能变为1月8日)。
  3. 日期范围判断逻辑缺陷:if (validStartDate < validEndDate)会跳过请假起始与结束为同一天的场景,导致当天请假天数未被统计。
  4. 循环边界误差:使用带时间的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 02:32:12