c#日期时间范围不包括特定范围

c#日期时间范围不包括特定范围,c#,datetime,enums,C#,Datetime,Enums,我有一个标志枚举: [Flags] public enum WeekDays { Monday = 1, Tuesday = 2, Wednesday = 4, Thursday = 8, Friday = 16, Saturday = 32, Sunday = 64 } 然后是一节课 public class Task { public Task() { } public int Days

我有一个标志枚举:

[Flags]
public enum WeekDays
{

    Monday = 1,
    Tuesday = 2,
    Wednesday = 4,
    Thursday = 8,
    Friday = 16,
    Saturday = 32,
    Sunday = 64
}
然后是一节课

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

所以基本上我想从总秒数中排除任务发生的时间段,即每周一、周二、周三00:00到06:00之间的时间段,即3x6小时=18小时,即64800秒


我需要通过将遮罩应用到时间范围来完成此操作…

这应该是您正在寻找的。我决定重命名你的类,因为C#中已经有一个
任务
类。此外,我还使其具有用于创建的factory方法,因为您需要对值进行一些检查。还要注意,需要从
DateTime
使用的
DayOfWeek
enum映射到
weekday
enum。基本上,您需要遍历两个
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 }
        };
}
将输出

2.06:00:00

-2.06:00:00

1.00:00:00

04:00:00

02:00:00

00:00:00

02:00:00

04:00:00


为什么不将
定义为
工作日
,而不是
int
task.Days=WeekDays.Monday | WeekDays.周二| WeekDays.周三
task.Days=7
更具可读性。当然我也可以将其定义为WeekDays…仅供参考,我已经更新了我的答案,以处理所有边缘情况,或者至少是我想到的那些情况。
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