c# DateTime范围排除特定范围

本文关键字:范围 排除 DateTime | 更新日期: 2023-09-27 18:09:54

我有一个Flags Enum:

[Flags]
public enum WeekDays
{
    Monday = 1,
    Tuesday = 2,
    Wednesday = 4,
    Thursday = 8,
    Friday = 16,
    Saturday = 32,
    Sunday = 64
}

然后是class

public class Task
{
     public Task()
     {
     }
     public int Days { get; set; }
     public TimeSpan Start { get; set; }
     public TimeSpan End { get; set; } 
}

假设以下值

 Task task = new Task();
 task.Days = 7; // from WeekDays enum: 7 = Monday, Tuesday, Wednesday
 task.Start = TimeSpan.Parse("00:00"); //midnight
 task.End =   TimeSpan.Parse("06:00"); //morning 06 AM

和特定范围周期:

 DateTime now = DateTime.Now;
 DateTime start = now.AddDays(-6);
 TimeSpan time = now - start;
 double toatlSeconds = time.TotalSeconds; // get total seconds between the start and now datetime range

如何从totalSeconds中减去任务的totalSeconds ?

所以基本上我想从totalSeconds中排除任务发生的时间段,即每个星期一,星期二,星期三在00:00到06:00之间,即3x6小时= 18小时,即64800秒?

我需要通过对时间范围应用蒙版来做到这一点

c# DateTime范围排除特定范围

这应该是您正在寻找的。我决定重命名你的类,因为在c#中已经有一个Task类。此外,我使它有工厂方法的创建,因为你想做一些检查的值。还需要注意从DateTime使用的DayOfWeek枚举到WeekDays枚举的映射。基本上,您需要遍历存在于两个DateTime s之间的每一天,以查看应该从总持续时间中删除多少时间。

public class ScheduledTask
{
    private ScheduledTask() { }
    public static ScheduledTask CreateTask(TimeSpan start, TimeSpan end, WeekDays days)
    {
        if (start < TimeSpan.Zero || start >= TimeSpan.FromDays(1))
        {
            throw new ArgumentOutOfRangeException("start");
        }
        if (end < TimeSpan.Zero || end >= TimeSpan.FromDays(1))
        {
            throw new ArgumentOutOfRangeException("end");
        }
        if (start > end)
        {
            throw new ArgumentException("End cannot be before Start", "end");
        }
        if ((int)days < 1 || (int)days >= 128)
        {
            throw new ArgumentOutOfRangeException("days");
        }
        return new ScheduledTask { Start = start, End = end, Days = days };
    }
    public WeekDays Days { get; private set; }
    public TimeSpan Start { get; private set; }
    public TimeSpan End { get; private set; }
    public TimeSpan DifferenceMinusTaskTime(DateTime from, DateTime to)
    {
        var actualFrom = from;
        var actualTo = to;
        if (from > to)
        {
            actualFrom = to;
            actualTo = from;
        }
        TimeSpan duration = TimeSpan.Zero;
        DateTime dayStart = actualFrom;
        DateTime dayEnd = actualFrom.Date == actualTo.Date 
                          ? actualTo 
                          : actualFrom.Date.AddDays(1);
        bool endIsNextDay = dayEnd.Date > dayStart.Date;
        while (dayStart < actualTo)
        {
            duration += dayEnd - dayStart;
            if (Days.HasFlag(mapping[dayStart.DayOfWeek]) 
                && dayStart.TimeOfDay < End
                && (dayEnd.TimeOfDay > Start || endIsNextDay))
            {
                if (dayStart.TimeOfDay < Start)
                {
                    if (dayEnd.TimeOfDay > End || endIsNextDay)
                    {
                        duration -= End - Start;
                    }
                    else
                    {
                        duration -= dayEnd.TimeOfDay - Start;
                    }
                }
                else 
                {
                    if (dayEnd.TimeOfDay > End || endIsNextDay)
                    {
                        duration -= End - dayStart.TimeOfDay;
                    }
                    else
                    {
                        duration -= dayEnd - dayStart;
                    }
                }
            }
            dayStart = dayEnd;
            dayEnd = dayStart.Date == actualTo.Date 
                     ? actualTo 
                     : dayStart.Date.AddDays(1);
            endIsNextDay = dayEnd.Date > dayStart.Date;
        }
        return from > to ? TimeSpan.Zero - duration : duration;
    }
    private Dictionary<DayOfWeek, WeekDays> mapping = 
        new Dictionary<DayOfWeek, WeekDays>
        {
            { DayOfWeek.Monday, WeekDays.Monday },
            { DayOfWeek.Tuesday, WeekDays.Tuesday },
            { DayOfWeek.Wednesday, WeekDays.Wednesday },
            { DayOfWeek.Thursday, WeekDays.Thursday },
            { DayOfWeek.Friday, WeekDays.Friday },
            { DayOfWeek.Saturday, WeekDays.Saturday },
            { DayOfWeek.Sunday, WeekDays.Sunday }
        };
}

加上上面的

var task = ScheduledTask.CreateTask(
    TimeSpan.FromHours(2),
    TimeSpan.FromHours(8),
    WeekDays.Monday | WeekDays.Tuesday | WeekDays.Wednesday);
Console.WriteLine(
    task.DifferenceMinusTaskTime(
        new DateTime(2015, 8, 24), 
        new DateTime(2015, 8, 27))); // 2 days 6 hours
Console.WriteLine(
    task.DifferenceMinusTaskTime(
       new DateTime(2015, 8, 27), 
       new DateTime(2015, 8, 24))); // -2 days 6 hours
Console.WriteLine(
    task.DifferenceMinusTaskTime(
        new DateTime(2015, 8, 28), 
        new DateTime(2015, 8, 29))); // 1 day
Console.WriteLine(
    task.DifferenceMinusTaskTime(
        new DateTime(2015, 8, 24), 
        new DateTime(2015, 8, 24, 10, 0, 0))); // 4 hours
Console.WriteLine(
    task.DifferenceMinusTaskTime(
        new DateTime(2015, 8, 24), 
        new DateTime(2015, 8, 24, 4, 0, 0))); // 2 hours
Console.WriteLine(
    task.DifferenceMinusTaskTime(
       new DateTime(2015, 8, 24, 4, 0, 0), 
       new DateTime(2015, 8, 24, 6, 0, 0))); // 0 hours
Console.WriteLine(
    task.DifferenceMinusTaskTime(
        new DateTime(2015, 8, 24, 4, 0, 0), 
        new DateTime(2015, 8, 24, 10, 0, 0))); // 2 hours
Console.WriteLine(
    task.DifferenceMinusTaskTime(
        new DateTime(2015, 8, 24, 10, 0, 0), 
        new DateTime(2015, 8, 24, 14, 0, 0))); // 4 hours

将输出

2.06:00:00

-2.06:00:00

1.00:00:00

04:00:00

02:00:00

就是

02:00:00

04:00:00