【问题标题】:How to Get the number of weeks in a given year如何获取给定年份的周数
【发布时间】:2013-06-30 13:55:58
【问题描述】:

尝试编写一个正确的函数来返回给定年份的周数,但没有成功。

我正在寻找的函数示例:

int weeks =  GetWeeksInYear ( 2012 )

应该返回 52 周 // 表示 2012 年只有 52 周。

P.s.:一年中可以是52、53、54周,不确定51左右

【问题讨论】:

  • 每年的周数相同。 (假设你有一个 int ......)唯一的区别(使用双精度时)将是闰年(你还有一天)
  • 这完全取决于你所说的“周”是什么意思。如果您说的是“ISO 周年中的一周”,那么它肯定会在 52 到 53 之间变化。如果您指的是其他内容,则需要非常具体。
  • @Vogel612:不,真的没有。一方面,您假设使用的是公历。另一方面,您假设“周”的一个含义 - 并且有各种不同的选项可用。 OP 肯定需要更清晰一些,但不是“总有 52 周”那么简单。
  • @svick 这不是辩论,他下次应该更具体,如果一个问题有这么多 cmets,而只有 1 个答案.. 这个问题不够具体:)
  • @illusion:我没有,因为您没有在问题中提供任何细节。提示提示。 (请注意,一年中的 54 周必须在我以前从未遇到过的日历中。)

标签: c# week-number


【解决方案1】:

查看Calendar.GetWeekOfYear 方法

public int GetWeeksInYear(int year)
{
      DateTimeFormatInfo dfi = DateTimeFormatInfo.CurrentInfo;
      DateTime date1 = new DateTime(year, 12, 31);
      Calendar cal = dfi.Calendar;
      return  cal.GetWeekOfYear(date1, dfi.CalendarWeekRule, 
                                          dfi.FirstDayOfWeek);
}

请仔细找出与客户习惯的文化相匹配的日历的正确 CalendarWeekRule 和 FirstDayOfWeek。 (对于某些压光机,它可能会有所不同...)

【讨论】:

  • 而且,同样重要的是,OP 应该自己决定他真正要求的是什么。
  • 请注意,.NET 中的 CalendarWeekRule 选项都不匹配 ISO-8601,如果这是 OP 想要的...
  • 我不会感到惊讶 OP 的新问题要求实施遵循公司规则的日历......在那里,做到了......
  • 当我在方法返回 53 后将 2018 年提供给 year 参数但它不正确,今年年底周为 52。
  • @MuratCanOĞUZHAN 那是实现中的一个错误,因为没有任何文化返回 52。这可能是由于缺乏适当的 ISO-8601 实现造成的。你可能想看看 NodaTime,Jon 为日期和时间处理编写的库
【解决方案2】:

2019 年 10 月 14 日更新

如果您使用 .NET Core 3.0 并且想要获得符合 ISO 8601 的一年中的周数 - 您可以使用 ISOWeek's GetWeeksInYear 方法。

using System;
using System.Globalization;

public class Program
{
    public static void Main()
    {
        Console.WriteLine(ISOWeek.GetWeeksInYear(2009)); // returns 53
    }
}

工作示例:https://dotnetfiddle.net/EpIbZQ

【讨论】:

    【解决方案3】:

    当我将 2018 年分配给其他方法的年份参数时,我遇到了问题。 我不知道也许有更快的代码,但我写了以下方法。

            //you can try like that 
            int weeks = DateHelper.GetWeeksInGivenYear(2018);
            int weeks = DateHelper.GetWeeksInGivenYear(2020);
    
            // This presumes that weeks start with Monday.
            // Week 1 is the 1st week of the year with a Thursday in it.
            public static int GetIso8601WeekOfYear(this DateTime time)
            {
                // Seriously cheat.  If its Monday, Tuesday or Wednesday, then it'll 
                // be the same week# as whatever Thursday, Friday or Saturday are,
                // and we always get those right
                DayOfWeek day = CultureInfo.InvariantCulture.Calendar.GetDayOfWeek(time);
                if (day >= DayOfWeek.Monday && day <= DayOfWeek.Wednesday)
                {
                    time = time.AddDays(3);
                }
    
                // Return the week of our adjusted day
                return CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(time, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
            }
    
            //gets given year last week no
            public static int GetWeeksInGivenYear(int year)
            {
                DateTime lastDate = new DateTime(year, 12, 31);
                int lastWeek = GetIso8601WeekOfYear(lastDate);
    
                while (lastWeek == 1)
                {
                    lastDate = lastDate.AddDays(-1);
                    lastWeek = GetIso8601WeekOfYear(lastDate);
    
                }
                return lastWeek;
            }
    

    【讨论】:

      【解决方案4】:

      P.s.:一年中可能是 52、53、54 周,不确定是 51 周

      1.如果我们使用日历检查,我们将得到只有 53 或 54 周的结果。

      2。这是不正确的结果(阅读我答案的结尾)

      您可以通过以下应用查看:

      using System;
      using System.Collections.Generic;
      using System.Drawing;
      using System.Globalization;
      using System.Linq;
      namespace TestConsoleApp
      {
          class Program
          {
              public static void Main(string[] args)
              {
                  var b = CountWeeksForYearsRange(1, 4000);
      
                  var c = b.Where(a => a.Value != 53).ToDictionary(a=>a.Key, a=>a.Value);
              }
      
              static DateTimeFormatInfo dfi = DateTimeFormatInfo.CurrentInfo;
              static Calendar calendar = DateTimeFormatInfo.CurrentInfo.Calendar;
      
              private static int CountWeeksInYear(int year)
              {
                  DateTime date = new DateTime(year, 12, 31);
                  return calendar.GetWeekOfYear(date, dfi.CalendarWeekRule, dfi.FirstDayOfWeek);
              }
      
              private static Dictionary<int,int> CountWeeksForYearsRange(int yearStart, int yearEnd)
              {
                  Dictionary<int, int> rez = new Dictionary<int, int>();
      
                  for (int i = yearStart; i <= yearEnd; i++)
                  {
                      rez.Add(i, CountWeeksInYear(i));
                  }
      
                  return rez;
              }
          }
      }
      

      只有 53 和 54 个值。

      这意味着为了更快地工作,我们可以为这种情况预先编码函数。


      没有 53 周的年份


      不是 53 周也不是 54 周的年份:


      所以在这种情况下,我们可以生成简单的年份数组,从 0 年到 4000 年有 54 周:

      12,40,68,96,108,136,164,192,204,232,260,288,328,356,384,412,440,468,496,508,536,564,592,604,632,660,688,728,756,784,812,840,868,896,908,936,964,992,1004,1032,1060,1088,1128,1156,1184,1212,1240,1268,1296,1308,1336,1364,1392,1404,1432,1460,1488,1528 ,1556,1584,1612,1640,1668,1696,1708,1736,1764,1792,1804,1832,1860,1888,1928,1956,1984,2012,2040,2068,2096,2108,2136,2164,2192 ,2204,2232,2260,2288,2328,2356,2384,2412,2440,2468,2496,2508,2536,2564,2592,2604,2632,2660,2688,2728,2756,2784,2812,2840,2868 ,2896,2908,2936,2964,2992,3004,3032,3060,3088,3128,3156,3184,3212,3240,3268,3296,3308,3336,3364,3392,3404,3432,3460,3488,3528 ,3556,3584,3612,3640,3668,3696,3708,3736,3764,3792,3804,3832,3860,3888,3928,3956,3984

      这意味着最优化的方法是:

      //Works only with 1-4000 years range
      public int CountWeeksInYearOptimized(int year)
      {
          return (_yearsWith54Weeks.IndexOf(year) == -1) ? 53 : 54;
      }
      private List<int> _yearsWith54Weeks = new List<int> { 12, 40, 68, 96, 108, 136, 164, 192,
                          204, 232, 260, 288, 328, 356, 384, 412, 440, 468, 496, 508, 536, 564,
                          592, 604, 632, 660, 688, 728, 756, 784, 812, 840, 868, 896, 908, 936,
                          964, 992, 1004, 1032, 1060, 1088, 1128, 1156, 1184, 1212, 1240, 1268,
                          1296, 1308, 1336, 1364, 1392, 1404, 1432, 1460, 1488, 1528, 1556, 1584,
                          1612, 1640, 1668, 1696, 1708, 1736, 1764, 1792, 1804, 1832, 1860, 1888,
                          1928, 1956, 1984, 2012, 2040, 2068, 2096, 2108, 2136, 2164, 2192, 2204,
                          2468, 2496, 2508, 2536, 2564, 2592, 2604, 2632, 2660, 2688, 2728, 2756,
                          2784, 2812, 2840, 2868, 2896, 2908, 2936, 2964, 2992, 3004, 3032, 3060,
                          3088, 3128, 3156, 3184, 3212, 3240, 3268, 3296, 3308, 3336, 3364, 3392,
                          3668, 3696, 3708, 3736, 3764, 3792, 3804, 3832, 3860, 3888, 3928, 3956,
                          3984 };
      

      或者如果您不想预先计算数据:

          DateTimeFormatInfo dfi = DateTimeFormatInfo.CurrentInfo;
          Calendar calendar = DateTimeFormatInfo.CurrentInfo.Calendar;
      
          private int CountWeeksInYear(int year)
          {
              DateTime date = new DateTime(year, 12, 31);
              return calendar.GetWeekOfYear(date, dfi.CalendarWeekRule, dfi.FirstDayOfWeek);
          }
      

      UPD:但是!看起来这是不正确的方式。

      我不知道为什么会这样,但看起来日历显示的数字不正确。正确的周数总是少于 1 周。您可以手动检查:

      让我们用日历计算接下来几年的天数:

      2011+2012+2013:

      53+54+53=160 周。

      但是停下来!

      (365+366+365)/7 = 157.

      所以最好的方法是对日历显示的值做-1

      或者使用以下最快的方法:

      //Works only with 1-4000 years range
      public int CountWeeksInYearOptimized(int year)
      {
          return (_yearsWith54Weeks.IndexOf(year) == -1) ? 52 : 53;
      }
      private List<int> _yearsWith54Weeks = new List<int> { 12, 40, 68, 96, 108, 136, 164, 192,
                          204, 232, 260, 288, 328, 356, 384, 412, 440, 468, 496, 508, 536, 564,
                          592, 604, 632, 660, 688, 728, 756, 784, 812, 840, 868, 896, 908, 936,
                          964, 992, 1004, 1032, 1060, 1088, 1128, 1156, 1184, 1212, 1240, 1268,
                          1296, 1308, 1336, 1364, 1392, 1404, 1432, 1460, 1488, 1528, 1556, 1584,
                          1612, 1640, 1668, 1696, 1708, 1736, 1764, 1792, 1804, 1832, 1860, 1888,
                          1928, 1956, 1984, 2012, 2040, 2068, 2096, 2108, 2136, 2164, 2192, 2204,
                          2468, 2496, 2508, 2536, 2564, 2592, 2604, 2632, 2660, 2688, 2728, 2756,
                          2784, 2812, 2840, 2868, 2896, 2908, 2936, 2964, 2992, 3004, 3032, 3060,
                          3088, 3128, 3156, 3184, 3212, 3240, 3268, 3296, 3308, 3336, 3364, 3392,
                          3668, 3696, 3708, 3736, 3764, 3792, 3804, 3832, 3860, 3888, 3928, 3956,
                          3984 };
      

      【讨论】:

        【解决方案5】:
        //For ISO Calender(First Day Of Week : Monday)  
        
        DateTime start = new DateTime(2020,1,1);
        int total_weeks=0;  
        
        //If a year starts on thursday or a leap year starts on wednesday then the year has 53 weeks
        
        if((DateTime.IsLeapYear(start.Year) && start.ToString("dddd")=="Wednesday")||(start.ToString("dddd")=="Thursday")) 
        {
            total_weeks=53;
        }
        else
        {
            total_week=52;
        }
        Console.WriteLine(total_weeks.ToString());
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-06
          • 1970-01-01
          相关资源
          最近更新 更多