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

本文关键字:时间 时间跨度 计算 | 更新日期: 2023-09-27 17:50:19

假设夜间时间从20.30到6.15 (AM)。这两个参数是用户作用域的变量。假设您有一个到达日期和一个离开日期,时间跨度从几分钟到超过一天。你怎样计算夜间的总时数?

public static double CalculateTotalNightTimeHours(DateTime arrival, 
                                                  DateTime departure,
                                                  int nightTimeStartHour, 
                                                  int nightTimeStartMinute, 
                                                  int nightTimeEndHour, 
                                                  int nightTimeEndMinute)
{ 
    //??
}

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

到目前为止的代码:

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;
}
//...

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

正因为我准备好了迎接挑战,所以您应该能够成功地使用下面的函数。请注意,这可能不是最有效的方法,但我这样做是为了展示逻辑。我可能会决定编辑这篇文章来改进它,但它应该可以正常工作。

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

  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;
    }
}

你可以这样称呼它:

double result = Calc(startDateTime, endDateTime, 20, 30, 6, 15);

基本上你需要计算夜晚开始和结束的时间。然后将这些数据与到达和离开日期进行比较,看看你是在夜晚开始后到达还是在夜晚结束前离开,从而得到你需要减去的值,从而确定夜晚的总时间。然后你需要每天继续计算这个,直到晚上的开始时间超过出发日期。这是我的解决方案。

public static double CalculateTotalNightTimeHours(
    DateTime arrival,
    DateTime departure,
    int nightTimeStartHour,
    int nightTimeStartMinute,
    int nightTimeEndHour,
    int nightTimeEndMinute)
{
    if (arrival >= departure)
        return 0;
    var nightStart = arrival.Date.AddHours(nightTimeStartHour).AddMinutes(nightTimeStartMinute);
    var nightEnd = nightStart.Date.AddDays(1).AddHours(nightTimeEndHour).AddMinutes(nightTimeEndMinute);
    double nightHours = 0;
    while (departure > nightStart)
    {
        if (nightStart < arrival)
            nightStart = arrival;
        if (departure < nightEnd)
            nightEnd = departure;
        nightHours += (nightEnd - nightStart).TotalHours;
        nightStart = nightStart.Date.AddDays(1).AddHours(nightTimeStartHour).AddMinutes(nightTimeStartMinute);
        nightEnd = nightStart.Date.AddDays(1).AddHours(nightTimeEndHour).AddMinutes(nightTimeEndMinute);
    }
    return nightHours;
}

您可能还需要添加检查以确保开始和结束小时在范围内。这里还假设黑夜从一天开始,在第二天结束,所以如果您希望黑夜在午夜之前结束,您就必须做其他事情。