TimeSpan 中一天的非活动间隔

Inactive Interval of a day in TimeSpan

提问人:Farshan 提问时间:11/5/2018 最后编辑:FCinFarshan 更新时间:11/5/2018 访问量:153

问:

我有一个名为 c# 类,它只接受 to 的所有属性的值。Slot0:00:001.00:00:00TimeSpan

public class Slot
{
    public TimeSpan StartTime { get; set; }

    public TimeSpan EndTime { get; set; }

}

我有这些值作为我的活动间隔,它们彼此不重叠:

var activeIntervals= new List<Slot>
{
    new Slot
    {
        StartTime = new TimeSpan(10,0,0),
        EndTime = new TimeSpan(12,0,0),
    },
    new Slot
    {
        StartTime = new TimeSpan(12,0,0),
        EndTime = new TimeSpan(13,0,0),
    },
    new Slot
    {
        StartTime = new TimeSpan(16,0,0),
        EndTime = new TimeSpan(22,0,0),
    }
};

是否有任何逻辑可以将一天中的其他间隔作为 inactiveIntervals?

在这种情况下,我想要这个结果:to 、to 和 to0:00:0010:00:0013:00:0016:00:0022:00:001.00:00:00

C# 间隔时间 跨度

评论

1赞 dumetrulo 11/5/2018
为什么要将时间表示为时间跨度
0赞 Lasse V. Karlsen 11/5/2018
只是您的示例没有碰巧重叠,还是您的系统根本不允许重叠?
0赞 Farshan 11/5/2018
@dumetrulo这是我的要求,我帮不了你。
2赞 Lasse V. Karlsen 11/5/2018
@dumetrulo 可能是因为 .NET 中没有“时间”数据类型
1赞 ctrl-alt-delor 11/5/2018
只是一个注释,因为没有回答问题。你有没有考虑过一年中最长的一天(今年英国的2018年10月28日),它有25个小时。

答:

2赞 Karan 11/5/2018 #1

请尝试以下逻辑。它会为你工作。

你可以在这里测试它

var activeIntervals = new List<Slot>
{
    new Slot
    {
        StartTime = new TimeSpan(10,0,0),
        EndTime = new TimeSpan(12,0,0),
    },
    new Slot
    {
        StartTime = new TimeSpan(12,0,0),
        EndTime = new TimeSpan(13,0,0),
    },
    new Slot
    {
        StartTime = new TimeSpan(16,0,0),
        EndTime = new TimeSpan(22,0,0),
    }
};


activeIntervals = activeIntervals.OrderBy(x => x.StartTime).ToList();

var inActiveIntervals = new List<Slot>();
TimeSpan start =  new TimeSpan(0,0,0);
TimeSpan end =  new TimeSpan(24,0,0);

for (int i = 0; i < activeIntervals.Count(); i++)
{
    if (start < activeIntervals[i].StartTime) 
    {
        inActiveIntervals.Add(new Slot { StartTime = start, EndTime = activeIntervals[i].StartTime });
    }
    start = activeIntervals[i].EndTime;
}            
if (start < end) 
{
    inActiveIntervals.Add(new Slot { StartTime = start, EndTime = end });
    start = end;
}
for (int i = 0; i < inActiveIntervals.Count(); i++)
{
     Console.WriteLine(inActiveIntervals[i].StartTime.ToString() + " - " + inActiveIntervals[i].EndTime.ToString());
}

评论

0赞 Farshan 11/5/2018
这就是我一直在寻找的。谢谢伙计
1赞 FCin 11/5/2018 #2

linq 的一个想法:

var inactiveIntervals = activeIntervals
    .Zip(activeIntervals.Skip(1), (first, second) => {
        if (second.StartTime - first.EndTime != TimeSpan.Zero) // Get rid of regions that don't have 'gap', e.g. 12:00:00 to 12:00:00
            return new Slot { StartTime = first.EndTime, EndTime = second.StartTime };
        return null;
    }).Where(a => a != null).ToList(); // Filter out nulls

// Insert range from start to first date
inactiveIntervals.Insert(0, new Slot { StartTime = TimeSpan.Zero, EndTime = activeIntervals[0].StartTime });
// Insert range from last date to end
inactiveIntervals.Add(new Slot { StartTime = activeIntervals.Last().EndTime, EndTime = new TimeSpan(1, 0, 0, 0) });

这使用了一个技巧,即您获取列表,然后将其压缩为移动 1 的相同列表。然后,您可以将一个元素与下一个元素进行比较。.ZipEndTimeStartTime

过滤没有间隙的区域有点丑陋。你必须检查边缘情况。

评论

0赞 Farshan 11/5/2018
这似乎太昂贵了。
0赞 FCin 11/5/2018
@Farshan 什么意思?
0赞 Farshan 11/5/2018
使用 linq 比循环链接非常昂贵
0赞 FCin 11/5/2018
@Farshan 不要优化不是瓶颈的东西。你怎么知道这是否会大大减慢你的应用程序速度?首先分析它。
0赞 Farshan 11/5/2018
因为优化是我首先关心的问题。但感谢您的即时帮助
1赞 Alexander 11/5/2018 #3

您需要创建新的实例,然后使用列表元素的迭代添加列表中不存在的日期间隔。List<Slot>activeIntervals

public static class SlotExtensions
{
    public static List<Slot> GetInactive(this List<Slot> slots)
    {
        Slot day = new Slot
        {
            StartTime = new TimeSpan(0,0,0),
            EndTime = new TimeSpan(24,0,0)
        }
        List<Slot> inactive = new List<Slot>();
        Slot tmp;
        foreach(Slot slot in slots)
        {
            if(day.StartTime < slot.StartTime)
            {
                tmp = new Slot
                {
                    StartTime = day.StartTime;
                    EndTime = slot.StartTime;
                };
                inactive.Add(tmp);
            };
            day.StartTime = slot.EndTime;
        }
        if(day.StartTime < day.EndTime)
        {
            inactive.Add(day);
        }
        return inactive;
    }
}

扩展方法使用 ,即类的实例,适合一整天。然后,我们将 和 迭代槽的起点之间的差异添加到新列表中,然后将 迭代槽的起点移位到终点。当循环结束时,metod 会将 remainig interval 添加到列表中。daySlotdayday