2

假设夜间时间设置为 20.30h 到 6.15h(AM)。这 2 个参数是用户范围的变量。假设您有一个到达日期和一个离开日期,可能从几分钟到一整天不等。你如何计算夜间的总小时数?

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

2 回答 2

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

然后你可以这样称呼它:

double result = Calc(startDateTime, endDateTime, 20, 30, 6, 15);
于 2013-01-02T15:21:13.787 回答
2

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

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

您可能还想添加检查以确保开始和结束时间在范围内。这也假设夜晚从一天开始,在第二天结束,所以如果你想让夜晚在午夜之前结束,你就必须做其他事情。

于 2013-01-02T15:23:46.043 回答