Click here to Skip to main content
15,860,943 members
Articles / Programming Languages / C#
Alternative
Tip/Trick

DateTime Extension Method to Give Week Number

Rate me:
Please Sign up or sign in to vote.
3.67/5 (3 votes)
19 Jul 2011CPOL2 min read 8.9K   1   2
DateTime Extension method to give the right week number
There certainly is a direct method in .NET to obtain the ISO week number. However, it is buggy, as ISO week numbering has been from VB 3.0 and Access Basic (of Access 1.0) through VBA of Office 2016, and not resolved in .NET. Fortunately, a tiny test for week 53 will get it right.

Improvement of the Original Tip

This method is as close to the default method of the framework as possible. While other perfectly valid methods exist, the method in the original tip builds on the native methods, but it fails when it comes to the ISO 8601 week numbering where week numbers cannot overlap.

For some reason, that is not clear, Microsoft has never – and that is since Visual Basic and Access Basic (of Access 1.x and 2.0) – followed the ISO 8601 method completely even though the method with the label “FirstFourDays” indicates this.

My alternative respects the original tip as well as the framework while correcting the incompleteness of it.

Check for Week Number 1

To get the correct ISO 8601 week number of any date, check if a week 53 is followed by a week 1. If the result is 2, the week number is not 53, but 1. Very simple and clear:

C#
using System;
using System.Globalization;

namespace DateTimeExtension
{
    /// <summary>
    /// Extended methods for System.DateTime.
    /// </summary>
    public static class DateTimeExtensionMethods
    {
        /// <summary>
        /// Count of days per week.
        /// </summary>
        private static int _daysInWeek = 7;

        /// <summary>
        /// Minimum and maximum week number according to ISO 8601.
        /// </summary>
        private static int _minIso8601WeekNumber = 1;
        private static int _maxIso8601WeekNumber = 53;
        
        #region WeekIso8601
        /// <summary>
        /// Gets the week number according to the ISO 8601 standard of this instance.
        /// <para>This is the corrected value from Calendar.GetWeekOfYear
        /// (this, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday)</para>
        /// </summary>
        /// <param name="currentDate">The current date</param>
        /// <returns>Returns the ISO 8601 week number of this instance.</returns>
        public static int WeekIso8601(this DateTime currentDate)
        {
            CultureInfo cultureInfo = CultureInfo.InvariantCulture;
            Calendar calendar = cultureInfo.Calendar;
            CalendarWeekRule calenderWeekRule = CalendarWeekRule.FirstFourDayWeek;
            DayOfWeek firstDayOfWeek = DayOfWeek.Monday;
            
            int weekNumber = calendar.GetWeekOfYear
                             (currentDate, calenderWeekRule, firstDayOfWeek);
            if (weekNumber.Equals(_maxIso8601WeekNumber))
            {
                // The week number appears to be 53. 
                // If so, the week number of the next week must be 1.
                // Obtain the week number of the next week and check if this is 1.
                int weekNumberNext = calendar.GetWeekOfYear
                        (currentDate.AddWeeks(1), calenderWeekRule, firstDayOfWeek);
                if (!weekNumberNext.Equals(_minIso8601WeekNumber))
                {
                    // The next week has week number 2.
                    // Thus, the current week number is not 53 but 1.
                    weekNumber = _minIso8601WeekNumber;
                }
            }
            return weekNumber;
        }
        
        #endregion
    }
}

Why Do It This Way?

That is partly to demonstrate that the native method is incomplete if you expect it to return true ISO 8601 week numbers, partly to demonstrate that you don’t have to reinvent the wheel by creating other methods that are more difficult to comprehend.

Also, this method builds on the Globalization objects which you already may be familiar with and – very likely – will use or reuse in other parts of your code when you deal with international week numbers.

Considerations

It is still difficult to collect information on many international matters including week numbering. The ISO organization, for example, doesn’t provide its standards for free, thus you either have to pay or to consult third party sources to find out. And - in this specific case - Microsoft delivers a method with a trap that you don’t see except if you read about it - or get caught.

History

  • 19th July, 2011: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect Cactus Data ApS
Denmark Denmark
Microsoft MVP, Most Valuable Professional, since 2017.

It started with BASIC in the 80s, then moved to PDC Prolog, and then - when Access 1.0 was launched - "back to Basic", or rather Access Basic. Then followed VBA (Visual Basic for Applications) starting with Microsoft Access 95/97 and still going with Access 2019/365.

Still I do some VBA, but since 2008 my main focus has been C#.

Application area is mainly accounting and custom applications related to accounting.

Comments and Discussions

 
QuestionAlternative solution Pin
realbart20-Sep-15 1:20
realbart20-Sep-15 1:20 
AnswerRe: Alternative solution Pin
Gustav Brock20-Sep-15 22:44
professionalGustav Brock20-Sep-15 22:44 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.