如何获得给定年份的周数

时间:2013-06-30 13:55:59

标签: c# week-number

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

我正在寻找的功能示例:

int weeks =  GetWeeksInYear ( 2012 )

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

P.s。:在一年中可以是52,53,54周,不确定是51

4 个答案:

答案 0 :(得分:15)

请参阅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。 (对于某些压光机,它可能会有所不同......)

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

  

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周的年份

enter image description here


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

enter image description here


因此,在这种情况下,我们可以生成简单的年份数组,其中包含从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 };

答案 3 :(得分:0)

  

更新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