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

如何在存在重叠日期的两列DateTime中查找时间间隙?

问题分析与解决方案

你的代码里有两个关键问题导致TimePeriod库无法识别重叠时段内的小时间隙:

  1. 排序未生效:organizeCurvePoints.OrderBy(t => t.EffectiveTime);这行仅生成了排序后的序列,但未赋值回原集合,原列表仍保持无序状态,会导致后续合并时段时逻辑混乱。
  2. 自定义类未实现ITimePeriod接口:TimePeriod库的CombinePeriods方法需要处理实现ITimePeriod接口的对象,你的CurveDateOrganizer只是普通类,库无法正确识别它的时间范围,合并后的时段自然不准确,间隙计算也就出错了。

修复后的代码实现

方案1:让CurveDateOrganizer实现ITimePeriod接口

修改自定义类,实现ITimePeriod接口,让库能正确解析时间范围:

[Serializable]
[DebuggerDisplay("EffectiveTime {EffectiveTime} TerminationTime {TerminationTime}", Name = "{DateOrganizer}")]
public class CurveDateOrganizer : ITimePeriod
{
    private DateTime _effectiveTime;
    private DateTime _terminationTime;

    public DateTime EffectiveTime
    {
        get => _effectiveTime;
        set
        {
            if (_effectiveTime != value)
            {
                _effectiveTime = value;
            }
        }
    }

    public DateTime TerminationTime
    {
        get => _terminationTime;
        set
        {
            if (_terminationTime != value)
            {
                _terminationTime = value;
            }
        }
    }

    // 实现ITimePeriod接口的属性和方法
    public DateTime Start => EffectiveTime;
    public DateTime End => TerminationTime;
    public TimeSpan Duration => TerminationTime - EffectiveTime;
    public bool IsReadOnly => false;
    public bool IsMoment => EffectiveTime == TerminationTime;

    public void Move(TimeSpan offset)
    {
        EffectiveTime += offset;
        TerminationTime += offset;
    }

    public void SetStart(DateTime start)
    {
        EffectiveTime = start;
    }

    public void SetEnd(DateTime end)
    {
        TerminationTime = end;
    }

    public void SetDuration(TimeSpan duration)
    {
        TerminationTime = EffectiveTime + duration;
    }

    public bool HasInside(DateTime moment)
    {
        return moment >= EffectiveTime && moment < TerminationTime;
    }

    public bool HasInside(ITimePeriod period)
    {
        return period.Start >= EffectiveTime && period.End <= TerminationTime;
    }

    public bool IntersectsWith(ITimePeriod period)
    {
        return !(period.End <= EffectiveTime || period.Start >= TerminationTime);
    }

    public bool OverlapsWith(ITimePeriod period)
    {
        return period.Start < TerminationTime && period.End > EffectiveTime;
    }

    public TimeSpan GetIntersectionDuration(ITimePeriod period)
    {
        var intersectStart = Max(EffectiveTime, period.Start);
        var intersectEnd = Min(TerminationTime, period.End);
        return intersectEnd > intersectStart ? intersectEnd - intersectStart : TimeSpan.Zero;
    }

    private DateTime Max(DateTime a, DateTime b) => a > b ? a : b;
    private DateTime Min(DateTime a, DateTime b) => a < b ? a : b;

    public CurveDateOrganizer(DateTime localEffectiveTime, DateTime localTerminationTime)
    {
        _effectiveTime = localEffectiveTime;
        _terminationTime = localTerminationTime;
    }
}

方案2:直接使用TimeRange替代自定义类(更简洁)

如果不需要自定义类的额外逻辑,直接用TimePeriod库自带的TimeRange会更省事:

// 替换原自定义类逻辑,直接生成TimeRange集合
var curvePeriodDates = new TimePeriodCollection();
foreach (var d in AllCurvePointsInRangeCopy)
{
    curvePeriodDates.Add(new TimeRange(d.LocalEffectiveTime, d.LocalTerminationTime));
}

// 按起始时间排序,确保时段顺序正确
curvePeriodDates.SortByStart();

// 定义总时间范围
var totalPeriod = new TimeRange(startDate, endDate);

// 合并所有有效时段
var combinedPeriods = new TimePeriodCombiner<TimeRange>().CombinePeriods(curvePeriodDates);

// 计算总时段内的间隙
var gaps = new TimeGapCalculator<TimeRange>().GetGaps(combinedPeriods, totalPeriod);

// 遍历输出间隙示例
foreach (var gap in gaps)
{
    Console.WriteLine($"间隙:{gap.Start:yyyy-MM-dd HH:mm} 至 {gap.End:yyyy-MM-dd HH:mm}");
}

关键修复点说明

  • 排序必须生效:无论是自定义类集合还是TimeRange集合,都要确保按起始时间排序,否则合并时段时会出现逻辑错误。
  • 确保时间对象符合库要求:要么让自定义类实现ITimePeriod接口,要么直接使用库自带的时间范围类,这样合并和间隙计算才能正确工作。
  • 简化逻辑:无特殊需求时,直接用库自带的TimeRange和TimePeriodCollection可减少自定义代码带来的兼容性问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 11:37:03