how to calculate number of weeks given 2 dates?

后端 未结 7 1921
耶瑟儿~
耶瑟儿~ 2020-12-11 15:45

I have two DateTime variables and i need to compute number of weeks between them.

What is the quickest (and correct) way to do this?

相关标签:
7条回答
  • 2020-12-11 15:53

    You could try the following:

    DateTime d1 = new DateTime(2006,10,1);
    DateTime d2 = new DateTime(2007,10,15);
    
    TimeSpan tt = d2 - d1;
    int totalWeeks = tt.Days/7;
    

    And if you want exact difference in fraction also then instead of:

    int totalWeeks = tt.Days/7;
    

    use:

    double totalWeeks = tt.TotalDays/7;
    
    0 讨论(0)
  • 2020-12-11 15:56

    UPDATE: Try this library: http://www.codeproject.com/Articles/168662/Time-Period-Library-for-NET The author has gone quite a ways to figure out all of these details.

    I'm not seeing an answer that really defines what a week is.

    Here's the pitfall, not all weeks are created equal. Some count Mondays whilst others count Thursdays.

    Take this month for example. If I want to count the number of weeks in August 2012 I could do something like:

    var date1 = new DateTime(2012,8,1);
    var date2 = new DateTime(2012,8,31);
    var weeks = (date1 - date2).TotalDays / 7;
    

    For one thing, .TotalDays gives us a double: weeks == 4.2857...

    We could round, but sometimes you'll over count. Other times you'll fall short.

    Counting weeks usually relies on defining when a week starts and ends. With DateTime objects we'll find every week starts on a Monday.

    The widely used ISO8601 standard defines a week starting Thursday. So the number of weeks between two dates relies on how many Thursdays occur.

    Implement something like this using the GregorianCalendar class:

    using System;
    using System.Globalization;
    using FluentAssertions;
    using NUnit.Framework;
    
    //...Namespace, test fixture class, etc ...
    
            [Test]
            public void GetMetricsTimesBetween_ReturnsCorrectRange() {
               DateTime startDate = new DateTime(2012, 8, 1);
               DateTime endDate = new DateTime(2012, 8, 31);
    
               var cal = new GregorianCalendar();
    
               int startWeekNumber = cal.GetWeekOfYear(startDate, 
                                                       CalendarWeekRule.FirstDay,                                      
                                                       DayOfWeek.Thursday);
               int endWeekNumber = cal.GetWeekOfYear(endDate, 
                                                    CalendarWeekRule.FirstDay,  
                                                    DayOfWeek.Thursday);
               int numberOfWeeksInRange = endWeekNumber - startWeekNumber;
    
               numberOfWeeksInRange.Should().Be(5);
            }
    

    This should give you more reliable results. You'll have to consider that this example is assuming we're counting weeks within the same year. With some extra work, you could help the calculation cope with date ranges that span different years:

    [Test]
    public void GetCountOfWeeks() {
       var startDate = new DateTime(2012, 12, 1); // 4 weeks here
       var endDate = new DateTime(2014, 1, 10); // 52 in 2013 and 2 weeks in 2014
       int numberOfWeeksInRange = 0;
    
       var cal = new GregorianCalendar();
    
       for (int year = startDate.Year; year <= endDate.Year; year++)
       {
           int startWeekNumber = 0;
           int endWeekNumber= 0;
    
           if(year == startDate.Year) { // start date through the end of the year
               startWeekNumber = cal.GetWeekOfYear(startDate, 
                   CalendarWeekRule.FirstDay, DayOfWeek.Thursday);
    
               endWeekNumber = cal.GetWeekOfYear((
                                      new DateTime(year + 1, 1, 1).AddDays(-1)),
                   CalendarWeekRule.FirstDay, DayOfWeek.Thursday);                       
           } else if(year == endDate.Year) { // start of the given year through the end date
               startWeekNumber = cal.GetWeekOfYear((new DateTime(year, 1, 1)),
                   CalendarWeekRule.FirstDay, DayOfWeek.Thursday);                       
    
               endWeekNumber = cal.GetWeekOfYear(endDate, 
                   CalendarWeekRule.FirstDay, DayOfWeek.Thursday);                   
           } else { // calculate the number of weeks in a full year                  
               startWeekNumber = cal.GetWeekOfYear(new DateTime(year, 1, 1),
                   CalendarWeekRule.FirstDay, DayOfWeek.Thursday);
    
               endWeekNumber = cal.GetWeekOfYear((
                                       new DateTime(year + 1, 1, 1).AddDays(-1)),
                   CalendarWeekRule.FirstDay, DayOfWeek.Thursday);                       
           }
    
           numberOfWeeksInRange += endWeekNumber - startWeekNumber;
       }
    
        numberOfWeeksInRange.Should().Be(58);
    } 
    

    This still isn't perfect, but it's closer. The point being here is that it's not as simple as we tend to make it if you want to get a true count of something like a "week" that is really more of a locale specific determination than some standard scientific expression like 1 + 1 = 2. Taking the total number of days and dividing by 7 is as ambiguous as saying all "work days" are 9 to 5 ...

    Here's a better example. Still could use refactoring, of course, but handles date ranges both in the same year and spanning multiple years as an extension to the GregorianCalendar class:

    /// <summary>
    /// Returns the number of weeks between two datetimes
    /// </summary>
    /// <param name="cal"></param>
    /// <param name="startDate"></param>
    /// <param name="endDate"></param>
    /// <returns></returns>
    public static int GetWeeks(this GregorianCalendar cal,
                                    CalendarWeekRule weekRule,
                                    DayOfWeek dayofWeek,
                                    DateTime startDate,
                                    DateTime endDate) {
        int startWeekNumber = 0;
        int endWeekNumber = 0;
        int numberOfWeeksInRange = 0;
    
        if (startDate.Year == endDate.Year) {
            startWeekNumber = 0;
            endWeekNumber = 0;
            startWeekNumber = cal.GetWeekOfYear(startDate,
                                                weekRule,
                                                dayofWeek);
    
            endWeekNumber = cal.GetWeekOfYear(endDate,
                                              weekRule,
                                              dayofWeek);
    
            numberOfWeeksInRange = endWeekNumber - startWeekNumber;
    
        }
        else { // calculate per year, inclusive
            for (int year = startDate.Year; year <= endDate.Year; year++) {
                startWeekNumber = 0;
                endWeekNumber = 0;
    
                if (year == startDate.Year) { // start date through the end of the year
                    startWeekNumber = cal.GetWeekOfYear(startDate, weekRule, dayofWeek);
    
                    endWeekNumber = cal.GetWeekOfYear((new DateTime(year + 1, 1, 1).AddDays(-1)),
                        weekRule, dayofWeek);
                }
                else if (year == endDate.Year) { // start of the given year through the end date
                    startWeekNumber = cal.GetWeekOfYear((new DateTime(year, 1, 1)),
                        weekRule, dayofWeek);
    
                    endWeekNumber = cal.GetWeekOfYear(endDate,
                        weekRule, dayofWeek);
                }
                else { // calculate the total number of weeks in this year                
                    startWeekNumber = cal.GetWeekOfYear(new DateTime(year, 1, 1),
                        weekRule, dayofWeek);
    
                    endWeekNumber = cal.GetWeekOfYear((new DateTime(year + 1, 1, 1).AddDays(-1)),
                        weekRule, dayofWeek;
                }
                numberOfWeeksInRange += endWeekNumber - startWeekNumber;
            }
        }
    
        return numberOfWeeksInRange;
    }
    
    0 讨论(0)
  • 2020-12-11 15:57

    You could try something like:

    var d1 = new DateTime(2011, 01, 05);
    var d2 = new DateTime(2010, 01, 05);
    
    Console.WriteLine((d1 - d2).Days / 7);
    

    You may need to round the result up or down depending on your exact requirement but that should do the trick.

    0 讨论(0)
  • 2020-12-11 15:58
    public static int NumberOfWeeks(DateTime dateFrom, DateTime dateTo)
    {
       TimeSpan Span = dateTo.Subtract(dateFrom);
    
       if (Span.Days <= 7)
       {
          if (dateFrom.DayOfWeek > dateTo.DayOfWeek)
          {
             return 2;
          }
    
          return 1;
       }
    
       int Days = Span.Days - 7 + (int)dateFrom.DayOfWeek;
       int WeekCount = 1;
       int DayCount = 0;
    
       for (WeekCount = 1; DayCount < Days; WeekCount++)
       {
          DayCount += 7;
       }
    
       return WeekCount;
    }
    
    0 讨论(0)
  • 2020-12-11 16:13

    It won't work if you try divise into integer. You must divide to double.

    DateTime startDateTime = new DateTime(2010, 8, 1);
    DateTime endDateTime = new DateTime(2010, 8, 28);
    double weeks = (endDateTime - startDateTime).TotalDays / 7;
    
    0 讨论(0)
  • 2020-12-11 16:15

    Use TimeSpan:

    double weeks = (date1 - date2).TotalDays / 7;
    
    0 讨论(0)
提交回复
热议问题