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

C# DateTime验证:处理跨午夜的活动班次时段问题

跨午夜班次的活动状态判断问题修复方案

问题背景

需要判断当前时间是否处于活动的有效班次区间内,规则如下:

  • 活动存储整体开始/结束时间(示例:2023-05-25 18:00:00 UTC 到 2023-06-01 04:00:00 UTC)
  • 班次为每日18:00-次日04:00(跨午夜时段),按工作日1-7存储
  • 当前时间在班次区间内时,活动状态设为Live,否则为Awaiting Start

现有逻辑存在错误:当当前时间处于午夜前的班次时段(18:00-23:59)时,会错误返回Awaiting Start;仅午夜后时段(00:00-04:00)能正确返回Live。现有代码如下:

public void SetStatus (T activity)
{
    //....
    if (startTime.Date <= DateTime.UtcNow.Date && finishTime.Date >= DateTime.UtcNow.Date)
    {
        if (finishTime.TimeOfDay < startTime.TimeOfDay)
            activity.Status = SetStatusIfShiftCrossesMidnight(startTime, finishTime);

        // ... 其他检查
    }
}

private string SetStatusIfShiftCrossesMidnight(DateTime startDate, DateTime finishDate)
{
    var now = DateTime.UtcNow;
    
    var start = new DateTime(now.Year, now.Month, now.Day - 1 , startDate.Hour, startDate.Minute, 
                startDate.Second, DateTimeKind.Utc);

    var finish = new DateTime(now.Year, now.Month, now.Day, finishDate.Hour, finishDate.Minute,
                finishDate.Second, DateTimeKind.Utc);

    if (start <= now && finish > now)
        return "Live"; 

    return "Awaiting Start";
}

核心问题分析

SetStatusIfShiftCrossesMidnight方法固定使用now.Day-1构建班次开始时间,仅覆盖了“当前时间在午夜后”的场景;当当前时间在午夜前的班次时段时,应该使用当天的班次开始时间,而不是前一天的,这正是错误的根源。

修复方案

优化后的班次判断方法

private string SetStatusIfShiftCrossesMidnight(DateTime activityStart, DateTime activityFinish)
{
    var now = DateTime.UtcNow;
    TimeSpan shiftStart = activityStart.TimeOfDay; // 班次开始时间(18:00)
    TimeSpan shiftEnd = activityFinish.TimeOfDay;   // 班次结束时间(04:00)

    DateTime currentShiftStart;
    DateTime currentShiftEnd;

    // 根据当前时间动态计算所属的班次区间
    if (now.TimeOfDay >= shiftStart)
    {
        // 当前时间在当天班次开始后(18:00-23:59),班次为当天18:00到次日04:00
        currentShiftStart = now.Date.Add(shiftStart);
        currentShiftEnd = currentShiftStart.AddDays(1).Date.Add(shiftEnd);
    }
    else
    {
        // 当前时间在当天班次结束前(00:00-04:00),班次为前一天18:00到当天04:00
        currentShiftStart = now.Date.AddDays(-1).Add(shiftStart);
        currentShiftEnd = now.Date.Add(shiftEnd);
    }

    // 校验当前班次是否在活动的整体有效期内,同时当前时间在班次区间内
    if (currentShiftStart >= activityStart && currentShiftEnd <= activityFinish 
        && now >= currentShiftStart && now < currentShiftEnd)
    {
        return "Live";
    }

    return "Awaiting Start";
}

优化后的主方法逻辑

public void SetStatus(T activity)
{
    DateTime activityStart = activity.Start;
    DateTime activityFinish = activity.Finish;
    var now = DateTime.UtcNow;

    // 先判断当前时间是否在活动的整体有效期内
    if (now < activityStart || now >= activityFinish)
    {
        activity.Status = "Awaiting Start";
        return;
    }

    // 处理跨午夜的班次
    if (activityFinish.TimeOfDay < activityStart.TimeOfDay)
    {
        activity.Status = SetStatusIfShiftCrossesMidnight(activityStart, activityFinish);
    }
    else
    {
        // 处理非跨午夜的班次(若有需求)
        activity.Status = (now.TimeOfDay >= activityStart.TimeOfDay && now.TimeOfDay < activityFinish.TimeOfDay) 
            ? "Live" 
            : "Awaiting Start";
    }
}

关键改进点

  • 动态匹配班次区间:根据当前时间的时段,自动选择使用当天或前一天的班次开始时间,覆盖所有有效时段
  • 增加活动有效期校验:确保当前班次在活动的整体时间范围内,避免误判超出活动时间的班次
  • 简化时间计算:使用Date.Add()替代手动构建DateTime,减少代码冗余和出错概率

内容的提问来源于stack exchange,提问作者jcx200

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 23:47:32