代码之家  ›  专栏  ›  技术社区  ›  Nasir

C-两个日期时间之间的持续时间(分钟)

  •  20
  • Nasir  · 技术社区  · 16 年前

    我需要确定两个约会时间之间的持续时间(分钟)。

    但是,有一个轻微的扭曲:

    • 不包括周末
    • 只计算分钟 在早上7点到晚上7点之间。 例如: [09/30/2010 6:39:00 PM] - [09/30/2010 7:39:00 PM] = 21 Minutes

    我只是很难想出一个像样的方法来做这件事,如果有人能提出建议,我会很感激的。

    谢谢。


    编辑:

    最后我提出了DTB的解决方案。只有一个特殊情况需要处理:如果结束时间在晚上7:00之后,请计算从早上7:00到实际结束时间的分钟数。

    我就是这样修改的:

    var minutes = from day in start.DaysInRangeUntil(end)
                    where !day.IsWeekendDay()
                    let st = Helpers.Max(day.AddHours(7), start)
                    let en = (day.DayOfYear == end.DayOfYear ? 
                                end :
                                Helpers.Min(day.AddHours(19), end)
                                )
                    select (en - st).TotalMinutes;
    

    再次感谢你的帮助。

    9 回复  |  直到 15 年前
        1
  •  23
  •   dtb    16 年前

    当然,您可以使用LINQ:

    DateTime a = new DateTime(2010, 10, 30, 21, 58, 29);
    DateTime b = a + new TimeSpan(12, 5, 54, 24, 623);
    
    var minutes = from day in a.DaysInRangeUntil(b)
                  where !day.IsWeekendDay()
                  let start = Max(day.AddHours( 7), a)
                  let end   = Min(day.AddHours(19), b)
                  select (end - start).TotalMinutes;
    
    var result = minutes.Sum();
    
    // result == 6292.89
    

    (注意:您可能需要检查很多我完全忽略的角落案例。)

    辅助方法:

    static IEnumerable<DateTime> DaysInRangeUntil(this DateTime start, DateTime end)
    {
        return Enumerable.Range(0, 1 + (int)(end.Date - start.Date).TotalDays)
                         .Select(dt => start.Date.AddDays(dt));
    }
    
    static bool IsWeekendDay(this DateTime dt)
    {
        return dt.DayOfWeek == DayOfWeek.Saturday
            || dt.DayOfWeek == DayOfWeek.Sunday;
    }
    
    static DateTime Max(DateTime a, DateTime b)
    {
        return new DateTime(Math.Max(a.Ticks, b.Ticks));
    }
    
    static DateTime Min(DateTime a, DateTime b)
    {
        return new DateTime(Math.Min(a.Ticks, b.Ticks));
    }
    
        2
  •  5
  •   Psytronic    16 年前

    开始的时间慢慢来,到当天结束的时间(即晚上7点)。

    然后,从第二天的早上7点开始,将天数计算到最后一天(不包括截止日期的任何时间)。

    计算过多少(如果有的话)周末。(每个周末减少2天)。

    从那里做一些简单的数学计算,以得到天数的总分钟数。

    将最后一天的额外时间和开始日期的额外时间相加。

        3
  •  4
  •   JaredPar    16 年前

    尝试以下diffrange函数。

    public static DateTime DayStart(DateTime date)
    {
        return date.Date.AddHours(7);
    }
    
    public static DateTime DayEnd(DateTime date)
    {
        return date.Date.AddHours(19);
    }
    
    public static TimeSpan DiffSingleDay(DateTime start, DateTime end)
    {
        if ( start.Date != end.Date ) {
            throw new ArgumentException();
        }
    
        if (start.DayOfWeek == DayOfWeek.Saturday || start.DayOfWeek == DayOfWeek.Sunday )
        {
            return TimeSpan.Zero;
        }
    
        start = start >= DayStart(start) ? start : DayStart(start);
        end = end <= DayEnd(end) ? end : DayEnd(end);
        return end - start;
    }
    
    public static TimeSpan DiffRange(DateTime start, DateTime end)
    {
        if (start.Date == end.Date)
        {
            return DiffSingleDay(start, end);
        }
    
        var firstDay = DiffSingleDay(start, DayEnd(start));
        var lastDay = DiffSingleDay(DayStart(end), end);
    
        var middle = TimeSpan.Zero;
        var current = start.AddDays(1);
        while (current.Date != end.Date)
        {
            middle = middle + DiffSingleDay(current.Date, DayEnd(current.Date));
            current = current.AddDays(1);
        }
    
        return firstDay + lastDay + middle;
    }
    
        4
  •  1
  •   Jon Hanna    16 年前
    static int WorkPeriodMinuteDifference(DateTime start, DateTime end)
    {
        //easier to only have to work in one direction.
        if(start > end)
            return WorkPeriodMinuteDifference(end, start);
        //if weekend, move to start of next Monday.
        while((int)start.DayOfWeek % 6 == 0)
            start = start.Add(new TimeSpan(1, 0, 0, 0)).Date;
        while((int)end.DayOfWeek % 6 == 0)
            end = end.Add(new TimeSpan(1, 0, 0, 0)).Date;
        //Move up to 07:00 or down to 19:00
        if(start.TimeOfDay.Hours < 7)
            start = new DateTime(start.Year, start.Month, start.Day, 7, 0, 0);
        else if(start.TimeOfDay.Hours > 19)
            start = new DateTime(start.Year, start.Month, start.Day, 19, 0, 0);
        if(end.TimeOfDay.Hours < 7)
            end = new DateTime(end.Year, end.Month, end.Day, 7, 0, 0);
        else if(end.TimeOfDay.Hours > 19)
            end = new DateTime(end.Year, end.Month, end.Day, 19, 0, 0);
    
        TimeSpan difference = end - start;
    
        int weeks = difference.Days / 7;
        int weekDays = difference.Days % 7;
        if(end.DayOfWeek < start.DayOfWeek)
            weekDays -= 2;
    
        return (weeks * 5 * 12 * 60) + (weekDays * 12 * 60) + difference.Hours * 60 + difference.Minutes
    }
    
        5
  •  1
  •   Jeremiah Nunn    16 年前

    我肯定我错过了什么。

      TimeSpan CalcBusinessTime(DateTime a, DateTime b)
      {
         if (a > b)
         {
            DateTime tmp = a;
            a = b;
            b = tmp;
         }
    
         if (a.TimeOfDay < new TimeSpan(7, 0, 0))
            a = new DateTime(a.Year, a.Month, a.Day, 7, 0, 0);
         if (b.TimeOfDay > new TimeSpan(19, 0, 0))
            b = new DateTime(b.Year, b.Month, b.Day, 19, 0, 0);
    
         TimeSpan sum = new TimeSpan();
         TimeSpan fullDay = new TimeSpan(12, 0, 0);
         while (a < b)
         {
            if (a.DayOfWeek != DayOfWeek.Saturday && a.DayOfWeek != DayOfWeek.Sunday)
            {
               sum += (b - a < fullDay) ? b - a : fullDay;
            }
            a = a.AddDays(1);
         }
    
         return sum;
      } 
    
        6
  •  1
  •   Musa Hafalir    16 年前

    这是一个很难回答的问题。对于一个简单的基本方法,我编写了以下代码:

    DateTime start = new DateTime(2010, 01, 01, 21, 00, 00);
    DateTime end = new DateTime(2010, 10, 01, 14, 00, 00);
    
    // Shift start date's hour to 7 and same for end date
    // These will be added after doing calculation:
    double startAdjustmentMinutes = (start - start.Date.AddHours(7)).TotalMinutes;
    double endAdjustmentMinutes = (end - end.Date.AddHours(7)).TotalMinutes;
    
    // We can do some basic
    // mathematical calculation to find weekdays count:
    // divide by 7 multiply by 5 gives complete weeks weekdays
    // and adding remainder gives the all weekdays:
    int weekdaysCount = (((int)((end.Date - start.Date).Days / 7) * 5) 
              + ((end.Date - start.Date).Days % 7));
    // so we can multiply it by minutes between 7am to 7 pm
    int minutes = weekdaysCount * (12 * 60);
    
    // after adding adjustment we have the result:
    int result = minutes + startAdjustmentMinutes + endAdjustmentMinutes;
    

    我知道这看起来不是程序上的美妙,但我不知道在开始和结束之间重复几天和几小时是否好。

        7
  •  1
  •   dana    16 年前

    我的实现方法是:快速计算总周数,然后一天一天地走剩下的周数……

    public TimeSpan Compute(DateTime start, DateTime end)
    {
        // constant start / end times per day
        TimeSpan sevenAM = TimeSpan.FromHours(7);
        TimeSpan sevenPM = TimeSpan.FromHours(19);
    
        if( start >= end )
        {
            throw new Exception("invalid date range");
        }
    
        // total # of weeks
        int completeWeeks = ((int)(end - start).TotalDays) / 7;
    
        // starting total
        TimeSpan total = TimeSpan.FromHours(completeWeeks * 12 * 5);
    
        // adjust the start date to be exactly "completeWeeks" past its original start
        start = start.AddDays(completeWeeks * 7);
    
        // walk days from the adjusted start to end (at most 7), accumulating time as we can...
        for(
            // start at midnight
            DateTime dt = start.Date;
    
            // continue while there is time left
            dt < end;
    
            // increment 1 day at a time
            dt = dt.AddDays(1)
        )
        {
            // ignore weekend
            if( (dt.DayOfWeek == DayOfWeek.Saturday) ||
                 (dt.DayOfWeek == DayOfWeek.Sunday) )
            {
                continue;
            }
    
            // get the start/end time for each day...
            // typically 7am / 7pm unless we are at the start / end date
            TimeSpan dtStartTime = ((dt == start.Date) && (start.TimeOfDay > sevenAM)) ?
                start.TimeOfDay : sevenAM;
            TimeSpan dtEndTime = ((dt == end.Date) && (end.TimeOfDay < sevenPM)) ?
                end.TimeOfDay : sevenPM;
    
            if( dtStartTime < dtEndTime )
            {
                total = total.Add(dtEndTime - dtStartTime);
            }
        }
    
        return total;
    }
    
        8
  •  1
  •   Michael Myers KitsuneYMG    16 年前

    使用TimeSpan.TotalMinutes,减去非工作日,减去多余的小时。

        9
  •  0
  •   sebagomez    16 年前

    我不会写任何代码,但是如果有一个日期时间,你就可以知道一周中的哪一天,这样你就知道你的工作范围内有多少个周末,这样你就可以知道一个周末有多少分钟。

    所以不会那么难…当然,必须有一个最佳的单线解…但我认为你可以利用这个。

    我忘了提一下,你也知道从下午7:00到早上7:00的分钟数,所以你所要做的就是将正确的分钟数减去你得到的时间差。