我需要检测有多少天有共同的2个日期间隔.为此,我在C#中使用了Itenso.TimePeriodNuget.但给出以下场景,我得到的结果是错误的:

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}");

但是由于两个间隔都是第14天和第15天,我预计结果是2,但控制台打印如下:

intersected 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

推荐答案

问题是,它将重叠计算为连续的时间范围.

如果将结束时间指定为new DateTime(2023, 7, 15),则表示指定了15号开始的午夜,因此不包括15号的其余时间.

当库与其他时间范围重叠时,它不会与15的任何时间范围重叠(可能除了开始时的一个刻度,但我在结果中看不到这一点).

要包括15号的全部时间,实际上必须将结束时间设置为16号午夜.

看起来在打开/关闭时间段处理中确实有一些微妙之处.

请考虑以下代码:

using System;
using Itenso.TimePeriod;

namespace Console1;

public static class Program
{
    public static void Main()
    {
        var start1 = new DateTime(2023, 7, 11);
        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 TimeInterval(start1, end1, startEdge: IntervalEdge.Closed, endEdge: IntervalEdge.Open),
            new TimeInterval(start2, end2, startEdge: IntervalEdge.Closed, endEdge: IntervalEdge.Closed),
        };

        var periodIntersector  = new TimePeriodIntersector<TimeRange>();
        var intersectedPeriods = periodIntersector.IntersectPeriods(periods);
        Console.WriteLine($"intersected days: {intersectedPeriods.Duration.TotalDays}");
    }
}

这将输出intersected days: 1.9999999999988427.

您可能认为它应该输出2.0,但因为第一个间隔的endEdge: IntervalEdge.Open,所以它不包括周期中16号开始的午夜-这意味着它也不包括15号结束的午夜(因为它们都是相同的时间).

因此,它在计算中省略了一个刻度.为了让它计算出您想要的值,您必须通过指定endEdge: IntervalEdge.Closed来实际包括结尾.

因为IntervalEdge.Closed实际上是缺省值,所以您可以完全省略它们,并通过在原始代码中将End of end1指定为第16位来获得正确的结果:

using System;
using Itenso.TimePeriod;

namespace Console1;

public static class Program
{
    public static void Main()
    {
        var start1 = new DateTime(2023, 7, 11);
        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}");
    }
}

另外:要注意Duration.Days(int,不包括部分天数)和Duration.TotalDays(double,确实包括部分天数)之间的区别.

Csharp相关问答推荐

将多个enum值传递给MAUI中的转换器参数的XML语法是什么?

在Linq中调用需要limit和offset的方法''''

向类注入一个工厂来创建一些资源是一个好的实践吗?

C#方法从AJAX调用接收NULL

UWP中的任务和界面

在.NET核心项目中创建Startup.cs比在Program.cs中注册服务好吗?

Automapper 12.x将GUID映射到字符串

用于管理System.Text.Json中的多态反序列化的自定义TypeInfoResolver

如果是,我怎么才能让这个加75,如果不是,我怎么才能减go 100?

未在Windows上运行的Maui项目

在';、';附近有错误的语法.必须声明标量变量";@Checkin";.';

是否可以从IQueryable T中获取一个IdentyEntry T>

用于ASP.NET核心的最小扩展坞

当我手动停止和关闭系统并打开时,Windows服务未启动

Maui:更改代码中的绑定字符串不会更新UI,除非重新生成字符串(MVVM)

使用LibraryImport在多个dll中导入相同的函数

反序列化我以前使用System.Text.Json序列化的文件时出现异常

这是T自身的布尔表达式是什么意思?

为什么我不能在固定语句中使用外部函数?

如何在flutter dart中使用publicKey.xml文件进行rsa加密,我遇到了问题Exception:Could not parse BigInt