【问题标题】:how to calculate number of weeks given 2 dates?如何计算给定2个日期的周数?
【发布时间】:2018-05-29 21:32:52
【问题描述】:

我有两个 DateTime 变量,我需要计算它们之间的周数。

最快(和正确)的方法是什么?

【问题讨论】:

  • 完整周数?如果是这样,一周从哪一天开始?还是相差天数/7?
  • 你如何定义正确?你能举一些关于不同输入的预期结果的例子吗?

标签: c# datetime


【解决方案1】:

使用TimeSpan:

double weeks = (date1 - date2).TotalDays / 7;

【讨论】:

  • 我没有看到在这个例子中 TimeSpan 被用在了哪里,我错过了什么吗?
  • @Aeron - 日期相减的结果是TimeSpan
  • 上述方法有1天的错误。它似乎不包括两个日期。将 Date1 视为 2016 年 8 月 1 日,将第二个日期视为 2016 年 8 月 2 日。减去后得到 1 天,但实际上有两天。
  • @shankbond 但实际上这两个日期之间是一天(24 小时)
【解决方案2】:

更新:试试这个库:http://www.codeproject.com/Articles/168662/Time-Period-Library-for-NET 作者已经想尽办法弄清楚所有这些细节。

我没有看到真正定义是什么的答案。

这是一个陷阱,并非所有的星期都是平等的。有些算星期一,有些算星期四。

以这个月为例。如果我想计算 2012 年 8 月的周数,我可以这样做:

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

一方面,.TotalDays 给了我们两倍: 周 == 4.2857...

我们可以四舍五入,但有时您会多算。其他时候你会功亏一篑。

计算周数通常取决于定义一周的开始和结束时间。使用 DateTime 对象,我们会发现每周都从星期一开始。

广泛使用的 ISO8601 标准定义了从星期四开始的一周。因此,两个日期之间的周数取决于有多少个星期四。

使用 GregorianCalendar 类实现类似的功能:

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

这应该会给你更可靠的结果。您必须考虑到这个例子是假设我们在同一年内计算周数。通过一些额外的工作,您可以帮助计算处理跨越不同年份的日期范围:

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

这仍然不完美,但更接近了。这里的重点是,如果您想获得像“周”这样的东西的真实计数,它并不像我们倾向于做的那么简单,这实际上更像是特定于语言环境的决定,而不是像 1 + 1 = 这样的标准科学表达式2. 将总天数除以 7 就像说所有“工作日”都是 9 到 5 一样模棱两可……

这是一个更好的例子。当然,仍然可以使用重构,但处理同一年份和跨多年的日期范围作为 GregorianCalendar 类的扩展:

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

【讨论】:

    【解决方案3】:

    您可以尝试以下方法:

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

    如果你也想要分数的精确差异,那么而不是:

    int totalWeeks = tt.Days/7;
    

    使用:

    double totalWeeks = tt.TotalDays/7;
    

    【讨论】:

      【解决方案4】:
      (dtTo - dtFrom).TotalDays / 7
      

      将给出周数

      【讨论】:

        【解决方案5】:
        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;
        }
        

        【讨论】:

          【解决方案6】:

          你可以试试这样的:

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

          您可能需要根据您的确切要求将结果向上或向下舍入,但这应该可以解决问题。

          【讨论】:

            【解决方案7】:

            如果您尝试除以整数,它将不起作用。你必须分到两倍。

            DateTime startDateTime = new DateTime(2010, 8, 1);
            DateTime endDateTime = new DateTime(2010, 8, 28);
            double weeks = (endDateTime - startDateTime).TotalDays / 7;
            

            【讨论】:

              猜你喜欢
              • 2010-09-21
              • 1970-01-01
              • 1970-01-01
              • 2015-07-11
              • 1970-01-01
              • 2016-05-07
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多