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

时间:2013-01-02 14:19:39

标签: c# .net winforms datetime timespan

假设夜间时间设定为20.30h至6.15h(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;
}
//...

2 个答案:

答案 0 :(得分:5)

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

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

  1. 'end'参数始终大于'start'参数(尽管我们检查了第一件事)
  2. 夜间参数早于夜间启动参数(即夜间时间在第二天结束,但从未超过24小时)
  3. 夏令时不存在! (这是一个棘手的问题,需要解决的一个重要问题是:如果您的开始或结束时间是时钟返回当天的01:30,您如何知道在回滚之前或之后是否记录了时间?这是时钟第一次或第二次命中01:30?)
  4. 考虑到这一点......

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

答案 1 :(得分: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;
}

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