How to Get the number of weeks in a given year
Asked Answered
B

5

12

Trying to code a correct function that returns the number of weeks in a given year, but without success.

Example of the function I'm looking for :

int weeks =  GetWeeksInYear ( 2012 )

should return 52 weeks // means there are only 52 weeks in 2012.

P.s.: in a year can be 52, 53, 54 weeks, not sure about 51

Bandore answered 30/6, 2013 at 13:55 Comment(17)
the number of weeks is the same every year. (given the case you have an int...) the only difference (when using a double) would be leap years (where you have one day more)Nakasuji
Isn't there always 52 whole weeks in a year (given that you are using an int and not a double / decimal) ?Divide
Whole weeks? Weeks starting Sunday? 52 * 7 = 364 there were 366 days in 2012...Beanstalk
It entirely depends on what you mean by "week". If you're talking "week of ISO week year" then it can definitely vary between 52 and 53. If you mean something else, you'll need to be very specific.Tying
@Vogel612: No, there really aren't. For one thing, you're assuming a Gregorian calendar. For another, you're assuming one meaning of "week" - and there are various different options available. The OP definitely needs to be clearer, but it's not as simple as "there are always 52 weeks".Tying
there is always 52 weeks in a year, but you may want to count how many Sundays in a year ?Destalinization
Depends on what standard you apply: ISO week starts on monday, the first week of a year has to contain at least four days. en.wikipedia.org/wiki/ISO_week_dateCrannog
@JonSkeet Doesn't “2012” and no mention of “alternative” calendars in a question written in English clearly imply Gregorian calendar?Baedeker
@Baedeker this is not a debate, he should be more specific next time, if a question has so many comments, and only 1 answer.. the question is not specific enough :)Mercerize
@svick: It's very likely that the OP is only interested in the Gregorian calendar - but my point is that the blanket statement is incorrect. Too many assumptions.Tying
@JonSkeet How did you come to know I'm talking about earth not mars years?Bandore
@illusion: I don't, because you didn't put any details into your question. Hint hint. (54 weeks in a year must be in a calendar I haven't come across before, mind you.)Tying
@JonSkeet I was replying on those who said in a year can be only 52 weeks, though it can be 54 as well Y2K)... rene though had enough logic to figure what I'm talking about.Bandore
@illusion: Well no - he guessed, and it's still not clear that his guess actually solves your problem. You still haven't said what sort of week you're talking about. As I said on the answer, if you're actually interested in ISO-8601 weeks, .NET classes don't provide that information themselves.Tying
@JonSkeet you better tell me, in general,how many sorts of calendar standards are there ( where number of weeks in a year vary)? and do you have 3 different functions that can be the correct answer to my question?Bandore
@illusion: There are lots of different calendars, and different ways of measuring weeks. As for "3 different functions" - the one given by rene might be what you're after, but you might be after ISO-8601 week-years, in which case you might want to look at my Noda Time library. We don't know what your requirements are though.Tying
Which week were 30 and 31/12/2012 in then? Seems to be the 53rd assuming Sunday is start of week. Last time I ran into all the assumptions around weeks in year, I managed to get the entire concept dropped, then they asked me for the number of months in a UK fiscal year 6/4/YYY to 5/4/YYYY at that point I started crying....Beanstalk
P
26

See the Calendar.GetWeekOfYear method

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

Be carefull to figure out the correct CalendarWeekRule and FirstDayOfWeek for a Calendar that matches the culture your customers are used to. (for some calenders it might vary...)

Polytonality answered 30/6, 2013 at 14:6 Comment(5)
And, just as importantly, the OP should decide for himself what he is really asking.Fiddling
And note that none of the CalendarWeekRule options in .NET match ISO-8601, if that's what the OP wants...Tying
I wouldn't be surprised to have new Question of the OP that asks for an implementation of a calendar that follows the company rules...been there, done that...Polytonality
when i give 2018 to year parameter after method returns 53 but it is not correct end of this year week is 52.Bodiless
@MuratCanOĞUZHAN That is then a bug in the implementation as none of the cultures return 52. It might be that the lack of a proper ISO-8601 implementation is causing this. You might want to look into NodaTime, the library that Jon wrote for date and time handlingPolytonality
B
5

Update 14 Oct 2019

If you're using .NET Core 3.0 and you want to get the number of weeks in a year conforming to ISO 8601 - you can use ISOWeek's GetWeeksInYear method.

using System;
using System.Globalization;

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

Working example: https://dotnetfiddle.net/EpIbZQ

Breechcloth answered 14/10, 2019 at 21:25 Comment(1)
For me the best option, finally .NET include a class to can get this data withount needing to implement your own method.Labio
W
2

I had the issue when I assign 2018 to year parameter of other methods, so I extended the Code of Tim Schmelter. I do not know, maybe there are codes that work faster:

//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;
}
Wallraff answered 2/8, 2018 at 13:0 Comment(2)
Part of this answer seems to be copied from here without proper attribution.Bitter
@ChristianGollhardt you are totally right I copied most of it inside somewhere in Stackoverflow. I'm gonna mention that one in the answer, I could also remove the answer but this answer fixed my problem in old wild times.Bodiless
B
1

P.s.: in a year can be 52, 53, 54 weeks, not sure about 51

1. If we will check With Calendar we will get results that we can have only 53 or 54 weeks.

2. This is incorrect result (read the end of my answer)

You can check it with the following app:

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

and there will be only 53 and 54 values.

This means that for faster work of method we can have pre-coded function for such situation.


Years with not 53 weeks

enter image description here


Years with not 53 and not 54 weeks:

enter image description here


So in this case we can generate simple array of years that have 54 weeks from 0 to 4000 years:

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

And this is means that most optimized method will be:

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

or if you don't want to pre-calculated data:

    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: BUT! Looks like this is incorrect way.

I don't know why so, but looks like Calendar saying incorrect number. And correct count of weeks is always on less on 1 week. You can check it manually:

Let's calc days in the following years with Calendar:

2011+2012+2013:

53+54+53=160 weeks.

But stop!

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

So best way will be to do -1 to the value that will be shown by calendar

Or to use the following fastest method:

//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 };
Baalbek answered 2/1, 2019 at 22:24 Comment(0)
M
0
//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());
Mug answered 14/3, 2022 at 13:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.