计算从时间跨度的总夜晚时间

Run*_*CMD 2 .net c# datetime timespan winforms

假设夜间时间设定为20.30h至6.15h(AM).这两个参数是用户范围的变量.假设您的到达日期和出发日期可以从几分钟到一天以上.你如何计算夜晚的总小时数?

public static double CalculateTotalNightTimeHours(DateTime arrival, 
                                                  DateTime departure,
                                                  int nightTimeStartHour, 
                                                  int nightTimeStartMinute, 
                                                  int nightTimeEndHour, 
                                                  int nightTimeEndMinute)
{ 
    //??
}
Run Code Online (Sandbox Code Playgroud)

编辑:我明白这可能不是直接的肯定/没有答案,但也许有人有一个优雅的解决方案来解决这个问题.回答评论:我确实想要计算用户可编辑的夜间开始和结束时间之间的总小时数(或分钟数).我正在计算访问时间,第一个日期确实是到达参数.

我的代码是:

DateTime nightStart = new DateTime( departure.Year, departure.Month, departure.Day,
                                    nightTimeStartHour, nightTimeStartMinute, 0);
DateTime nightEnd = new DateTime( arrival.Year, arrival.Month, arrival.Day,
                                  nightTimeEndHour, nightTimeEndMinute, 0);
if (arrival < nightEnd)
{
    decimal totalHoursNight = (decimal)nightEnd.Subtract(arrival).TotalHours;
}
//...
Run Code Online (Sandbox Code Playgroud)

mus*_*fan 5

仅仅因为我能够应对挑战,您应该能够成功使用以下功能.请注意,这可能不是最有效的方法,但我这样做,所以我可以列出逻辑.我可能决定编辑它作为改进它的一些点,但它应该可以正常工作.

在这里注意几个假设也很重要:

  1. 'end'参数总是大于'start'参数(尽管我们检查的是第一件事)
  2. 夜间参数早于夜间启动参数(即夜间时间在第二天结束,但从未在24小时后结束)
  3. 夏令时不存在!(这是一个棘手的关注,为解决一个重要的问题是:如果你要么开始或结束时间为01:30时在当天的时钟回去,你怎么会知道,如果时间之前或回滚后记录即?这是时钟第一次或第二次命中01:30?)

考虑到这一点...

public static double Calc(DateTime start, DateTime end, int startHour, int startMin, int endHour, int endMin)
{
    if (start > end)
        throw new Exception();//or whatever you want to do

    //create timespans for night hours
    TimeSpan nightStart = new TimeSpan(startHour, startMin, 0);
    TimeSpan nightEnd = new TimeSpan(endHour, endMin, 0);

    //check to see if any overlapping actually happens
    if (start.Date == end.Date && start.TimeOfDay >= nightEnd && end.TimeOfDay <= nightStart)
    {
        //no overlapping occurs so return 0
        return 0;
    }

    //check if same day as will process this differently
    if (start.Date == end.Date)
    {
        if (start.TimeOfDay > nightStart || end.TimeOfDay < nightEnd)
        {
            return (end - start).TotalHours;
        }

        double total = 0;
        if (start.TimeOfDay < nightEnd)
        {
            total += (nightEnd - start.TimeOfDay).TotalHours;
        }
        if(end.TimeOfDay > nightStart)
        {
            total += (end.TimeOfDay - nightStart).TotalHours;
        }
        return total;
    }
    else//spans multiple days
    {
        double total = 0;

        //add up first day
        if (start.TimeOfDay < nightEnd)
        {
            total += (nightEnd - start.TimeOfDay).TotalHours;
        }
        if (start.TimeOfDay < nightStart)
        {
            total += ((new TimeSpan(24, 0, 0)) - nightStart).TotalHours;
        }
        else
        {
            total += ((new TimeSpan(24, 0, 0)) - start.TimeOfDay).TotalHours;
        }

        //add up the last day
        if (end.TimeOfDay > nightStart)
        {
            total += (end.TimeOfDay - nightStart).TotalHours;
        }
        if (end.TimeOfDay > nightEnd)
        {
            total += nightEnd.TotalHours;
        }
        else
        {
            total += end.TimeOfDay.TotalHours;
        }

        //add up any full days
        int numberOfFullDays = (end - start).Days;
        if (end.TimeOfDay > start.TimeOfDay)
        {
            numberOfFullDays--;
        }
        if (numberOfFullDays > 0)
        {
            double hoursInFullDay = ((new TimeSpan(24, 0, 0)) - nightStart).TotalHours + nightEnd.TotalHours;
            total += hoursInFullDay * numberOfFullDays;
        }

        return total;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以这样称呼它:

double result = Calc(startDateTime, endDateTime, 20, 30, 6, 15);
Run Code Online (Sandbox Code Playgroud)

  • 重叠测试可以简单地说:`start.Date == end.Date && start.TimeOfDay> = nightEnd && end.TimeOfDay <= nightStart`,因为`start <= end`. (2认同)