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

Itenso.TimePeriod计算时间区间天数交集结果异常问题排查

问题:Itenso.TimePeriod计算日期区间交集天数不符预期

我使用C#的Itenso.TimePeriod NuGet包计算两个日期区间的共同天数,但测试结果不符合预期:

测试场景:

  • 区间1:2023-07-11 至 2023-07-15
  • 区间2:2023-07-14 至 2023-08-01
    预期交集天数为2天(7月14日、15日),但实际输出1天。

初始测试代码

var start1 = new DateTime(2023, 7, 11);
var end1 = new DateTime(2023, 7, 15);

var start2 = new DateTime(2023, 7, 14);
var end2 = new DateTime(2023, 8, 1);

var periods = new TimePeriodCollection
{
    new TimeRange(start1, end1),
    new TimeRange(start2, end2),
};
var periodIntersector = new TimePeriodIntersector<TimeRange>();
var intersectedPeriods = periodIntersector.IntersectPeriods(periods);
Console.WriteLine($"intersected days: {intersectedPeriods.Duration.Days}");

修改后的代码及输出

尝试调整结束时间和区间闭合方式后,结果仍为1天:

var start1 = new DateTime(2023, 7, 11);
var end1 = new DateTime(2023, 7, 15)+ TimeSpan.FromSeconds(1);

var start2 = new DateTime(2023, 7, 14);
var end2 = new DateTime(2023, 8, 1);

var t1 = new TimeRange(start1, end1, true);
var t2 = new TimeRange(start2, end2, true);

var timeInterval1 = new TimeInterval(start1, end1);
timeInterval1.EndEdge = IntervalEdge.Open;
timeInterval1.StartEdge = IntervalEdge.Open;

var timeInterval2 = new TimeInterval(start2, end2);
timeInterval2.EndEdge = IntervalEdge.Open;
timeInterval2.StartEdge = IntervalEdge.Open;

var periods = new TimePeriodCollection
{
    t1,t2
};
var periodIntersector = new TimePeriodIntersector<TimeRange>();

var intersectedPeriods = periodIntersector.IntersectPeriods(periods);

Console.WriteLine($"intersected days: {intersectedPeriods.Duration.Days}");
Console.WriteLine($"intersected days: {t1.GetIntersection(t2).Duration.Days}");

输出:

intersected days: 1
intersected days: 1

问题原因与解决办法

核心原因

Itenso.TimePeriod中的TimeRange默认采用左闭右开的区间规则:

  • 包含起始时间点
  • 不包含结束时间点

初始测试中,end1 = new DateTime(2023,7,15)对应的是7月15日00:00:00,因此区间1实际覆盖的是2023-07-11 00:00:00 至 2023-07-15 00:00:00(不含),并不包含7月15日全天。两个区间的交集仅为7月14日一天,所以输出1天。

你尝试添加1秒的方式无效,因为结束时间变成7月15日00:00:01,区间仅包含这1秒,Duration.Days取整数部分仍为1。

正确解决方式

方式1:调整结束时间为次日0点(推荐)

将区间的结束时间设置为目标日期的次日0点,利用左闭右开规则覆盖目标日期全天:

var start1 = new DateTime(2023, 7, 11);
// 结束时间设为7月16日0点,确保包含7月15日全天
var end1 = new DateTime(2023, 7, 16);

var start2 = new DateTime(2023, 7, 14);
var end2 = new DateTime(2023, 8, 1);

var periods = new TimePeriodCollection
{
    new TimeRange(start1, end1),
    new TimeRange(start2, end2),
};
var periodIntersector = new TimePeriodIntersector<TimeRange>();
var intersectedPeriods = periodIntersector.IntersectPeriods(periods);
Console.WriteLine($"intersected days: {intersectedPeriods.Duration.Days}");
// 输出:intersected days: 2

方式2:设置闭区间(包含起止时间)

显式将区间的StartEdge和EndEdge设为Closed,此时需要注意天数计算需基于实际区间覆盖范围调整:

var start1 = new DateTime(2023, 7, 11);
var end1 = new DateTime(2023, 7, 15);

var start2 = new DateTime(2023, 7, 14);
var end2 = new DateTime(2023, 8, 1);

// 创建闭区间
var t1 = new TimeRange(start1, end1) 
{ 
    StartEdge = IntervalEdge.Closed, 
    EndEdge = IntervalEdge.Closed 
};
var t2 = new TimeRange(start2, end2) 
{ 
    StartEdge = IntervalEdge.Closed, 
    EndEdge = IntervalEdge.Closed 
};

var intersection = t1.GetIntersection(t2);
// 闭区间下,需额外判断是否包含结束日来计算完整天数
var days = (intersection.End - intersection.Start).Days + 
           (intersection.EndEdge == IntervalEdge.Closed && intersection.End.TimeOfDay == TimeSpan.Zero ? 1 : 0);
Console.WriteLine($"intersected days: {days}");
// 输出:intersected days: 2

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 10:22:31