取反日期在同一天

问题描述

我想知道是否有人可以帮助我,所以我在一天之内收集了工作的开始时间和结束时间。我也想表明相反的情况,所以那天那个人没有工作的时间。我的代码遇到的问题是,它要延续到第二天,而我只想那天。

public class WorkDay
{
    public DateTime Day { get; set; }
    public List<Worked> WorkingTimes { get; set; }
}

public class Worked
{
    public DateTime Start { get; set; }
    public DateTime End { get; set; }
}


static class Program
{

    static void Main()
    {

    var Now = DateTime.Now;
    var year = Now.Year;
    var month = Now.Month;
    var day = Now.Day;

    var Day = new WorkDay
    {
        Day = Now,WorkingTimes = new List<Worked>
        {
            new Worked { Start = new DateTime(year,month,day,8,30,0),End = new DateTime(year,10,0) },new Worked { Start = new DateTime(year,45,14,0)  },50,0).AddHours(10) }
        }
    };

        foreach (var time in Day.WorkingTimes)
            Console.WriteLine($"Start {time.Start} " + $"End {time.End}");

        Day.WorkingTimes = Day.WorkingTimes.OrderBy(x => x.Start).ToList();

        var opposite = Opposite(Day);

        foreach (var time in opposite)
            Console.WriteLine($"Start {time.Start} " + $"End {time.End}");

        Console.WriteLine("Hello World!");
    }

    public static IEnumerable<Worked> Opposite(WorkDay workDay)
    {
        var rested = new List<Worked>();

        for (var i = workDay.WorkingTimes.Count(); i-- > 0;)
            if (i - 1 != -1 && workDay.WorkingTimes[i - 1].End != workDay.WorkingTimes[i].Start)
                rested.Add(new Worked { Start = workDay.WorkingTimes[i - 1].End,End = workDay.WorkingTimes[i].Start });

        rested = rested.OrderBy(x => x.Start).ToList();

        var lastEntry = rested.Last().End.Date;
        var lastTime = new DateTime(lastEntry.Year,lastEntry.Month,lastEntry.Day,23,59,59);

        if (lastTime > rested.Last().End)
            rested.Add(new Worked
            { Start = workDay.WorkingTimes.Last().End,End = lastTime });

        return rested;
    }

}

所以输出将是: 工作:

Start 21/09/2020 08:30:00 End 21/09/2020 10:30:00
Start 21/09/2020 10:45:00 End 21/09/2020 14:30:00
Start 21/09/2020 14:50:00 End 22/09/2020 00:50:00

相反:

Start 21/09/2020 10:30:00 End 21/09/2020 10:45:00
Start 21/09/2020 14:30:00 End 21/09/2020 14:50:00
Start **22/09/2020** 00:50:00 End 21/09/2020 23:59:59

要做的是第二天不计算差额。因此,在WorkDay类中有Day,并且所有日期都必须从该天开始。

因此要考虑当天的24小时(无论工作与否),因此,如果他们不工作,则应在相反方法的结果之内进行计算。

解决方法

一个简单的解决方案可能是仅通过restedStartEnd匹配的那些值来过滤Day结果

// last line of method "Opposite"
return rested.Where(o => o.Start.Date == workDay.Day.Date && o.End.Date == workDay.Day.Date);
,

我将通过对一段时间进行建模来解决此问题,然后提供一种可以Cut从该时期中抽出一段时间的方法。这样一来,剩下的时间就变得微不足道了。

让我们从Period类开始:

private sealed class Period : IEquatable<Period>
{
    public DateTime StartTime { get; private set; }
    public DateTime EndTime { get; private set; }

    public Period(DateTime startTime,DateTime endTime)
    {
        this.StartTime = startTime;
        this.EndTime = endTime;
    }

    public override bool Equals(object obj)
    {
        if (obj is Period)
            return Equals((Period)obj);
        return false;
    }

    public bool Equals(Period obj)
    {
        if (obj == null)
            return false;
        if (!EqualityComparer<DateTime>.Default.Equals(this.StartTime,obj.StartTime))
            return false;
        if (!EqualityComparer<DateTime>.Default.Equals(this.EndTime,obj.EndTime))
            return false;
        return true;
    }

    public override int GetHashCode()
    {
        int hash = 0;
        hash ^= EqualityComparer<DateTime>.Default.GetHashCode(this.StartTime);
        hash ^= EqualityComparer<DateTime>.Default.GetHashCode(this.EndTime);
        return hash;
    }

    public override string ToString()
    {
        return String.Format("{{ StartTime = {0},EndTime = {1} }}",this.StartTime,this.EndTime);
    }

    public IEnumerable<Period> Cut(Period that)
    {
        if (that.StartTime <= this.StartTime)
        {
            if (that.EndTime <= this.StartTime)
            {
                yield return this;
            }
            else if (that.EndTime < this.EndTime)
            {
                yield return new Period(that.EndTime,this.EndTime);
            }
        }
        else if (that.StartTime < this.EndTime)
        {
            if (that.EndTime < this.EndTime)
            {
                yield return new Period(this.StartTime,that.StartTime);
                yield return new Period(that.EndTime,this.EndTime);
            }
            else
            {
                yield return new Period(this.StartTime,that.StartTime);
            }
        }
        else
        {
            yield return this;
        }
    }
}

现在我们可以这样表示当前的工作时间:

var workingTimes = new[]
{
    new Period(new DateTime(year,month,day,8,30,0),new DateTime(year,10,0)),new Period(new DateTime(year,45,14,50,0).AddHours(10)),};

那整天是:

var whole = new Period(now.Date,now.Date.AddDays(1.0));

现在我们可以像这样计算一天的剩余时间:

var result = new [] { whole };
foreach (var d in workingTimes)
{
    result = result.SelectMany(r => r.Cut(d)).ToArray();
}

我的最终结果是:

2020/09/21 00:00 - 2020/09/21 08:30 
2020/09/21 10:30 - 2020/09/21 10:45 
2020/09/21 14:30 - 2020/09/21 14:50