c#获取时间跨度内的工作时间

c# Get working hours within a time span

给定多个时间跨度,如何获得一个数组来告诉我发言的工作时间。

工作时间从09:00开始,到17:00结束

示例:

  1. 2017 年 11 月 15 日 16:00 - 2017 年 11 月 17 日 12:00 -> 应该给我一个 [1,8,3][=12= 的数组]

  2. 2017 年 11 月 15 日 09:00 - 2017 年 11 月 17 日 12:00 -> 应该给我一个 [8,8,1] 的数组(这看起来很简单因为我可以做 Hrs / 8 和 Hrs % 8 来得到结果。)

  3. 2017 年 11 月 16 日 15:00 - 2017 年 11 月 17 日 15:00 -> 应该给我一个 [2,6]

这是目前给我开始时间和结束时间之间的总工作时间的方法:

protected double getWorkingHrs(DateTime _dtTaskStart, DateTime _dtTaskEnd)
{
    double count = 0;

    for (var i = _dtTaskStart; i < _dtTaskEnd; i = i.AddHours(1))
    {
        if (i.DayOfWeek != DayOfWeek.Saturday && i.DayOfWeek != DayOfWeek.Sunday)
        {
            if (i.TimeOfDay.Hours >= 9 && i.TimeOfDay.Hours < 17)
            {
                count++;
            }
        }
    }

    return count;
}

如有任何帮助,我们将不胜感激。

任务在 8 小时内显示为这样。所以当我添加一个 20 小时的任务时,我必须将它们分解成组并在网格中显示它们。我必须将它们分开,因为不同日期的任务可能会分配给不同的用户并且可能有不同的注释等。

干杯

虽然不是最漂亮的(恕我直言,通过增加时间在日期时间上进行棘轮循环有点不雅。),您的函数可以进行调整以提供可枚举的工作时间(或工作时间,因为它们更多)通常称为)每天如下:

protected IEnumerable<double> getWorkingHrsPerDay(DateTime _dtTaskStart, DateTime _dtTaskEnd)
{
    double count = 0;
    DateTime lastHandledDate = _dtTaskStart.Date;
    for (var i = _dtTaskStart; i < _dtTaskEnd; i = i.AddHours(1))
    {
        if (i.DayOfWeek != DayOfWeek.Saturday && i.DayOfWeek != DayOfWeek.Sunday)
        {
            if (i.TimeOfDay.Hours >= 9 && i.TimeOfDay.Hours < 17)
            {
                count++;
            }
        }
        //if we have started to count the hours for a new day
        if (lastHandledDate.Date != i.Date)
        {
            lastHandledDate = i.Date;
            double hourCount = count;
            //reset our hour count
            count = 0;
            //we return the count of the last day
            yield return hourCount;
        }
        lastHandledDate = i.Date;
    }
}

然后您可以使用 LINQ 的 ToArray 方法执行以下操作:

double[] hoursPerDay = getWorkingHrsPerDay(beginDate, endDate).ToArray();

这是您的问题的解决方案:

    public static double[] GetWorkHours(DateTime start, DateTime end, TimeSpan workStartTime, TimeSpan workEndTime)
    {
        IList<double> result = new List<double>();

        if (start > end)
        {
            throw new ArgumentException("Start date is later than end date");
        }

        DateTime currentDate = start.Date;
        while (currentDate <= end.Date)
        {
            if (currentDate.DayOfWeek != DayOfWeek.Saturday && currentDate.DayOfWeek != DayOfWeek.Sunday)
            {
                TimeSpan realStartTime = GetStartTimeForDay(start, end, workStartTime, currentDate);
                TimeSpan realEndTime = GetEndTimeForDay(start, end, workEndTime, currentDate);

                if (realStartTime >= workEndTime || realEndTime <= workStartTime)
                {
                    result.Add(0);
                }
                else
                {
                    result.Add(GetHoursInTimePeriod(realStartTime, realEndTime));
                }
            }

            currentDate = currentDate.AddDays(1);
        }

        return result.ToArray();
    }

    private static TimeSpan GetStartTimeForDay(DateTime start, DateTime end, TimeSpan workStartTime, DateTime day)
    {
        return day == start.Date ? (start.TimeOfDay < workStartTime ? workStartTime : start.TimeOfDay) : workStartTime;
    }

    private static TimeSpan GetEndTimeForDay(DateTime start, DateTime end, TimeSpan workEndTime, DateTime day)
    {
        return day == end.Date ? (end.TimeOfDay < workEndTime ? end.TimeOfDay : workEndTime) : workEndTime;
    }

    private static double GetHoursInTimePeriod(TimeSpan start, TimeSpan end)
    {
        return (end - start).TotalHours;
    }