基于DateTime.Now和预定义小时数比较检测工作班次。c#

基于DateTime.Now和预定义小时数比较检测工作班次。c#,c#,date-comparison,timeofday,C#,Date Comparison,Timeofday,我希望我的程序在新的轮班开始时重置统计信息。 我的轮班时间预定义为: 白班:周一至周四4:00-16:25(周五至周日4:00-15:55) 夜班:周一至周四16:25-4:00(周五至周日15:55-4:00) 这就是我目前正在做的,它是有效的,但我不知道当班次结束时是在上午时如何进行时间比较,所以现在当班次结束时设置为23:59:59时,它是有效的,但当我将其更改为凌晨4点时,它就倒下了 DateTime d1 = new DateTime(2020, 01, 01, 1

我希望我的程序在新的轮班开始时重置统计信息。 我的轮班时间预定义为:

  • 白班:周一至周四4:00-16:25(周五至周日4:00-15:55)
  • 夜班:周一至周四16:25-4:00(周五至周日15:55-4:00)
这就是我目前正在做的,它是有效的,但我不知道当班次结束时是在上午时如何进行时间比较,所以现在当班次结束时设置为23:59:59时,它是有效的,但当我将其更改为凌晨4点时,它就倒下了

        DateTime d1 = new DateTime(2020, 01, 01, 16, 25, 00); //Mon-Thur shift change
        DateTime d2 = new DateTime(2020, 01, 01, 15, 55, 00); //Fri-Sun shift change
        DateTime d3 = new DateTime(2020, 01, 01, 23, 59, 59); //Evening shift end
        DateTime d4 = new DateTime(2020, 01, 01, 04, 00, 00); //Morning shift start
        DateTime d5 = DateTime.Now;


        if (d5.DayOfWeek == DayOfWeek.Monday || d5.DayOfWeek == DayOfWeek.Tuesday || d5.DayOfWeek == DayOfWeek.Wednesday || d5.DayOfWeek == DayOfWeek.Thursday)
        {
            if (d5.TimeOfDay >= d4.TimeOfDay && d5.TimeOfDay < d1.TimeOfDay)
            {
                dayShift = true;
                eveShift = false;
            }
        }
        if (d5.DayOfWeek == DayOfWeek.Friday || d5.DayOfWeek == DayOfWeek.Saturday || d5.DayOfWeek == DayOfWeek.Sunday)
        {
            if (d5.TimeOfDay >= d4.TimeOfDay && d5.TimeOfDay < d2.TimeOfDay)
            {
                dayShift = true;
                eveShift = false;
            }
        }
        if (d5.DayOfWeek == DayOfWeek.Monday || d5.DayOfWeek == DayOfWeek.Tuesday || d5.DayOfWeek == DayOfWeek.Wednesday || d5.DayOfWeek == DayOfWeek.Thursday)
        {
            if (d5.TimeOfDay >= d1.TimeOfDay && d5.TimeOfDay < d3.TimeOfDay)
            {
                dayShift = false;
                eveShift = true;
            }
        }
        if (d5.DayOfWeek == DayOfWeek.Friday || d5.DayOfWeek == DayOfWeek.Saturday || d5.DayOfWeek == DayOfWeek.Sunday)
        {
            if (d5.TimeOfDay >= d2.TimeOfDay && d5.TimeOfDay < d3.TimeOfDay)
            {
                dayShift = false;
                eveShift = true;
            }
        }
DateTime d1=新的日期时间(2020,01,01,16,25,00)//周一至周四换班
DateTime d2=新的日期时间(2020,01,01,15,55,00)//星期五太阳移动变化
DateTime d3=新的日期时间(2020,01,01,23,59,59)//夜班结束
DateTime d4=新的日期时间(2020,01,01,04,00,00)//早班开始
DateTime d5=DateTime.Now;
如果(d5.DayOfWeek==星期一| | d5.DayOfWeek==星期二| | d5.DayOfWeek==星期三| | d5.DayOfWeek==星期四)
{
如果(d5.TimeOfDay>=d4.TimeOfDay&&d5.TimeOfDay=d4.TimeOfDay&&d5.TimeOfDay=d1.TimeOfDay&&d5.TimeOfDay=d2.TimeOfDay&&d5.TimeOfDay
我能做些什么来比较一天的时间和上午的时间


我想检查一下时间是否在d1和d4之间。有什么想法吗?

我会改变这里的方法。与其说是一组时间,不如在对象中定义构成“移位”定义的内容,列出这些对象的列表,然后遍历它们并根据它们测试当前日期/时间

结果比我乍一看想的要复杂得多,因为周二凌晨2点33分实际上是周一夜班的结束时间,我想

但我会这样做:

public enum ShiftType
{
    Unknown, //default..
    Day,
    Night
}

public class DailyShiftDetail
{

    public IEnumerable<DayOfWeek> DaysOfWeek {get;set;}
    public DateTime Start { get; set; }
    public DateTime End { get; set; }
    public ShiftType Type { get; set; }
}
public class ShiftCheck
{
    //define shifts on each day.  This data could come from a database or something
    private static IEnumerable<DailyShiftDetail> shifts = new List<DailyShiftDetail>
    {
        new DailyShiftDetail
        {
            //Mon-Thu daytime shift
            DaysOfWeek=new[]
            {
                DayOfWeek.Monday, DayOfWeek.Tuesday, DayOfWeek.Wednesday, DayOfWeek.Thursday 
            },
            Start = new DateTime(2000,1,1,4,0,0), //4AM
            End = new DateTime(2000,1,1,16,25,0),  //4:25PM
            Type=ShiftType.Day
        },
        new DailyShiftDetail
        {
            //Fri-Sun daytime shift
            DaysOfWeek=new[]
            {
                DayOfWeek.Friday, DayOfWeek.Saturday, DayOfWeek.Sunday 
            },
            Start = new DateTime(2000,1,1,04,0,0), //4AM
            End = new DateTime(2000,1,1,15,55,0),  //3:55PM
            Type=ShiftType.Day
        },            
        new DailyShiftDetail
        {
            //Mon-Thu Evening shift
            DaysOfWeek=new[]
            {
                DayOfWeek.Monday, DayOfWeek.Tuesday, DayOfWeek.Wednesday, DayOfWeek.Thursday 
            },
            Start = new DateTime(2000,1,1,16,25,0),
            End = new DateTime(2000,1,1,4,0,0),
            Type=ShiftType.Night
        },
        new DailyShiftDetail
        {
            //Fri-Sun Evening shift
            DaysOfWeek=new[]
            {
                DayOfWeek.Friday, DayOfWeek.Saturday, DayOfWeek.Sunday 
            },
            Start = new DateTime(2000,1,1,15,55,0),
            End = new DateTime(2000,1,1,4,0,0),
            Type=ShiftType.Night
        }
    };

    public static ShiftType GetShiftTypeForDate(DateTime testDate)
    {                        
        //you could probably do this all with a .Where() or
        //.FirstOrDefault, but the logic in the LINQ stuff
        //would end up being a bit painful.  This is probably
        //a little less efficient but will perform fine,
        //and the logic is easier to follow.
        DailyShiftDetail matchingShift = null;

        foreach(var testShift in shifts)
        {
            var shiftStart = testShift.Start.TimeOfDay;
            var shiftEnd = testShift.End.TimeOfDay;

            //check logic differently for evening shifts,
            //as not only are the times going over midnight,
            //but in fact 2AM on a tuesday is a *Monday EVENING* shift...
            //So we need to check the following days too..               
            if (shiftStart > shiftEnd)
            {                    
                //if the testing time is earlier than the end of shift, then it's between
                //midnight and the shift time.  
                if (testDate.TimeOfDay < shiftEnd)                        
                {
                    //we need to work out what day this 'shift' would have started on...
                    //this will not be the DayOfWeek of the passed-in time, but the day before...
                    //just cast to int, subtract one, account for rollover and cast back to DayOfWeek...
                    int dayBefore = (int)testDate.DayOfWeek - 1;
                    if (dayBefore < 0) 
                    {
                        dayBefore = 6;
                    }
                    var dayOfWeekBefore = (DayOfWeek)dayBefore;

                    //now we've worked out the theoretical day the shift starts, we can test that.
                    if (testShift.DaysOfWeek.Contains(dayOfWeekBefore))
                    {
                        matchingShift = testShift;
                    }
                }
                //otherwise, if the test time of day is after the start of the shift then we can check the
                //current day and if that matches the shift we can return it too
                else if (
                    testDate.TimeOfDay > shiftStart
                    && testShift.DaysOfWeek.Contains(testDate.DayOfWeek))
                {
                    matchingShift = testShift;
                }
            }
            else
            {
                //daytime shift.
                //simple logic.  Day matches and test time between start and end.
                //Assume end time is EXCLUSIVE as otherwise 4:00AM EXACTLY is in two different shifts..
                if (
                    testShift.DaysOfWeek.Contains(testDate.DayOfWeek)
                    && testShift.Start.TimeOfDay <= testDate.TimeOfDay
                    && testShift.End.TimeOfDay > testDate.TimeOfDay
                    )
                {
                    matchingShift = testShift;                    
                }
            }

            //if we found a match, stop looping through shifts.
            if (matchingShift != null)
            {
                break;
            }                                    
        }

        if (matchingShift == null)
        {
            //couldn't work it out, so return this...
            return ShiftType.Unknown;
        }
        //found a shift record, return its type.
        return matchingShift.Type;
    }
}

我只是简单地测试了其中的一些逻辑错误,但应该很容易调试……

有趣的方法,我稍后会测试它。谢谢你花时间在这上面。你的想法实际上打开了我对这个问题的心扉……这真的很有魅力,绝对解决了我的问题。一开始似乎有点让人望而生畏,但当你通读它时,一切都变得清晰起来。非常感谢你想出这个主意!没问题,乍一看,我觉得很简单,但当我走过去的时候,它变得更复杂了。一个半相关的主题:这类棘手的小问题将是尝试一些TDD的一个极好的例子-您可以很容易地知道给定一系列日期的预期结果,围绕这些日期编写一些测试,并使用函数直到它们都通过。使用像Ncrunch这样的工具,这是一个非常令人满意的体验(尽管很遗憾它不是免费的)。。。非常吸引人,我简要地阅读了Ncrunch的工作,并很想尝试一下,不过159美元。我通过将系统时钟和日期更改为一周中的每一天和每一小时来测试您的解决方案,它可以完美地工作。
//Today, tuesday 22nd @ 5:55pm.. would be an evening shift?
var nightShift = ShiftCheck.GetShiftTypeForDate(
    new DateTime(2020, 9, 22, 17, 55, 0));
//is ShiftType.Night

//today, tuesday 22nd @ 6AM... would be a day shift?
var dayShift = ShiftCheck.GetShiftTypeForDate(
    new DateTime(2020, 9, 22, 6, 0, 0));
//is ShiftType.Day

//a friday at 15:57 would be a night shift
var friNightShift = ShiftCheck.GetShiftTypeForDate(
    new DateTime(2020, 9, 18, 15, 57, 0));
//is ShiftType.Night

//a Wednesday at 15:57 would be a DAY shift though
var wedDayShift = ShiftCheck.GetShiftTypeForDate(
    new DateTime(2020, 9, 16, 15, 57, 0));
//is ShiftType.Day.