Peter's Gekko

Sponsors

The Lounge

News

Advertisement

Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
ISO weeknumbers of a date, a C# implementation

The DateTime class in the .NET framework is very rich in methods for manipulating and computing dates. In my former language Delphi working with dates was no fun. All had to be done by manipulating strings but given the fact that nobody can agree on what comes first, day or month, all code was tricky and prone to bugs.

The only thing which is missing in the class is a weeknumber property. Every workweek has its own number. In Europe this is very often used. There is an ISO 8601 standard which describes how this number is calculated: Week 01 of a year is per definition the first week that has the Thursday in this year, which is equivalent to the week that contains the fourth day of January.

There are plenty of implementations to be found on the web to calculate this number. Finding a good one in C# took some assembling. This one is based on a Delphi implementation on the SDN site. Thanks to the DateTime class it needs only a fraction of the code.

        private int weekNumber(DateTime fromDate)
        {
            // Get jan 1st of the year
            DateTime startOfYear = fromDate.AddDays(- fromDate.Day + 1).AddMonths(- fromDate.Month +1);
            // Get dec 31st of the year
            DateTime endOfYear = startOfYear.AddYears(1).AddDays(-1);
            // ISO 8601 weeks start with Monday
            // The first week of a year includes the first Thursday
            // DayOfWeek returns 0 for sunday up to 6 for saterday
            int[] iso8601Correction = {6,7,8,9,10,4,5};
            int nds = fromDate.Subtract(startOfYear).Days  + iso8601Correction[(int)startOfYear.DayOfWeek];
            int wk = nds / 7;
            switch(wk)
            {
                case 0 :
                    // Return weeknumber of dec 31st of the previous year
                    return weekNumber(startOfYear.AddDays(-1));
                case 53 :
                    // If dec 31st falls before thursday it is week 01 of next year
                    if (endOfYear.DayOfWeek < DayOfWeek.Thursday)
                        return 1;
                    else
                        return wk;
                default : return wk;
            }
        }
 

The nice thing I used from the Delphi sample was the iso8601 correction array using the day of the week as index.

It would be even nicer to add the method as a property to a derived DateTime class. Alas that class is sealed.


Posted 09-26-2005 8:11 AM by pvanooijen
Filed under:

[Advertisement]

Comments

daughtkom wrote re: ISO weeknumbers of a date, a C# implementation
on 09-26-2005 9:49 AM
In VB, you can do this:

DateAndTime.DatePart(DateInterval.WeekOfYear, DateTime.Now, FirstDayOfWeek.Sunday, FirstWeekOfYear.FirstFourDays)

The DateAndTime module is in the Microsoft.VisualBasic namespace, and syntax for the DatePart function is as follows (from MSDN):

Public Overloads Function DatePart( _
ByVal Interval As String, _
ByVal DateValue As Object, _
Optional ByVal DayOfWeek As FirstDayOfWeek = FirstDayOfWeek.Sunday, _
Optional ByVal WeekOfYear As FirstWeekOfYear = FirstWeekOfYear.Jan1 _
) As Integer

The choices for FirstWeekOfYear are:
FirstWeekOfYear.System
FirstWeekOfYear.Jan1
FirstWeekOfYear.FirstFourDays
FirstWeekOfYear.FirstFullWeek

Am I missing something else, or could you just use Microsoft.VisualBasic.DateAndTime.DatePart(...) to do this? To be honest, I've never had occasion to use week number myself.
pvanooijen wrote re: ISO weeknumbers of a date, a C# implementation
on 09-26-2005 12:04 PM
That will work as well. You can even use it in C#.

Add Microsoft.VisualBasic to the reference of your C# project

Add this to the uses clause

using Microsoft.VisualBasic;

An alternative implementation would be :

private int weekNumberVB(DateTime fromDate) {
return DateAndTime.DatePart(DateInterval.WeekOfYear, fromDate, Microsoft.VisualBasic.FirstDayOfWeek.Monday, FirstWeekOfYear.FirstFourDays);

}

FirstDayOfWeek is ambigious, you have to fully qualify that one.

Nice :) And even shorter.

Christopher Steen wrote Link Listing - September 26, 2005
on 09-26-2005 10:18 PM
.NET Master Class in Reston, VA [Via: gsnowman ]
.NET Rocks Comes to Town [Via: gsnowman ]
[.NET...
Oskar Austegard wrote re: ISO weeknumbers of a date, a C# implementation
on 09-27-2005 8:08 AM
Keep in mind that there are different rules for calculating weeknumbers, depending on location. The issue is with what week to consider as the first week of the year (is it the first complete week, or the first week that has the majority of days in the new year?, etc).

A few years ago, my then-employer's European divisions requested weeknumbers in our intranet application's calendar controls. At the time there were no controls I could find that would handle this. But I did some research and contacted Peter Blum, who had provided the Date package controls we were using. He was very open to adding the feature to the controls, and I was more than happy to test the added features.

A screenshot of the week number column can be seen half-way down the page here: http://www.peterblum.com/DateControls/CSCalendarHome.aspx
pvanooijen wrote re: ISO weeknumbers of a date, a C# implementation
on 09-27-2005 2:37 PM
There are indeed different ways to calculate these, with the many parameters of the VB DatePart function you can get any result you want. ISO is trying to standardize the weeknumbers by explicitly stating how to calculate. My implementation folllows ISO.
In the Netherlands week numbers are often used, since the ISO standard is there people are beginning to agree on them. Before that there were differences. Leading to b2b misunderstandings.

Yves Reynhout wrote re: ISO weeknumbers of a date, a C# implementation
on 09-30-2005 8:47 AM
Ever checked out System.Globalization?
In this example CalendarWeekRule and DayOfWeek should be thought of as configurable.

public static int GetWeekOfYear(DateTime date){
return System.Threading.Thread.CurrentThread.CurrentCulture.Calendar.GetWeekOfYear(date, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
}
pvanooijen wrote re: ISO weeknumbers of a date, a C# implementation
on 09-30-2005 11:20 AM
OK, who needs VB ?
It's all in the framework.

A variation which adapts itself to the culture of the runtime environment :
System.Globalization.CultureInfo myCI = System.Threading.Thread.CurrentThread.CurrentCulture;
int weekNo = myCI.Calendar.GetWeekOfYear(date, myCI.DateTimeFormat.CalendarWeekRule, myCI.DateTimeFormat.FirstDayOfWeek);

For the Dutch code CalenderWeekRule and FirstDayOfWeek comply with ISO.

Thanks.
Goffen wrote re: ISO weeknumbers of a date, a C# implementation
on 05-15-2006 7:01 AM
NONE of your code work correctly for instance for the the last week of 2003   See http://konsulent.sandelien.no/VB_help/Week/

(also for a solution in vb/c#)


According to the ISO 8601 rulebook, the week number of the transitionweek
between two years, is linked to the year in which that week has most days.
The final week of 2003 / first week of 2004 had three days in 2003 and four
days in 2004 and should therefore in its entirety have been associated with
2004 (as week number 1).
pvanooijen wrote re: ISO weeknumbers of a date, a C# implementation
on 05-15-2006 7:52 AM
@ Goffen: I don't agree.

ISO 8601 states "first thursday", not your quote. How many days in a week that is depends on which day is day 1 of the week. Opinions on that vary !

Herbee wrote re: ISO weeknumbers of a date, a C# implementation
on 01-05-2007 4:20 AM

... but pvanooijen's opinion doesn't matter in this case. ISO 8601, section 3.28, defines Monday as the first day of the week.

pvanooijen wrote re: ISO weeknumbers of a date, a C# implementation
on 01-06-2007 4:33 AM

@ Herbee: I miss your point. My point is that there are several definitions for first day of the week around, one of them is ISO.

I do agree that's the one to follow but, as written in the original post, not al software producing week numbers follows ISO (yet).

For the first week of the year it's of no importance which day of the week comes first. First thirsday, as ISO says.

Yves Goergen wrote re: ISO weeknumbers of a date, a C# implementation
on 06-13-2008 10:25 AM

Is there a way to reverse that calculation? The only thing I find on the web is converting date to week number. Now when the user enters a year and a week number, I need to get the Monday (first day) of that week. How can that be done? Try, error and iterate?

Please reply via e-mail to nospam@unclassified.de.

jonelf wrote re: ISO weeknumbers of a date, a C# implementation
on 01-07-2009 10:14 AM

System.Globalization.CultureInfo myCI = System.Threading.Thread.CurrentThread.CurrentCulture;

int weekNo = myCI.Calendar.GetWeekOfYear(

new DateTime(2008,12,31), myCI.DateTimeFormat.CalendarWeekRule, myCI.DateTimeFormat.FirstDayOfWeek);

The above sets weekNo to 53. This is not correct according to ISO 8601. Seems the framework misses a parameter that says that only full weeks are allowed.

The VB.NET DateAndTime  fails in the same way.

pvanooijen wrote re: ISO weeknumbers of a date, a C# implementation
on 01-13-2009 3:44 AM

As I read it ISO 8601 does not say anything about week 53, it just defines when week 1 starts.Which might result in a year with 53 weks.

Peter wrote re: ISO weeknumbers of a date, a C# implementation
on 06-13-2009 6:00 PM

The point in jonelf's comment is not that there can't be 53 weeks in a year (which is possible as you say according to ISO 8601) but rather that 2008-12-31 was a Wednesday which makes 2009-01-01 a Thursday which makes that week number 1 and not 53.

See en.wikipedia.org/.../ISO_week_date for more information.

jonelf wrote re: ISO weeknumbers of a date, a C# implementation
on 06-21-2009 5:08 PM

Thank you Peter, that's exactly what I tried to say.

A couple of minutes ago I tried the same in Mono and it also returns week 53.

PS. Totally unrelated but Ruby gets it right:

>> Date.parse("2008-12-31").strftime("%V")

=> "01"

DS.

jonelf wrote re: ISO weeknumbers of a date, a C# implementation
on 06-21-2009 6:28 PM

Here's a hack from Shawn Steele that also gives the ISO 8601 week.

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

blogs.msdn.com/.../iso-8601-week-of-year-format-in-microsoft-net.aspx

Add a Comment

(required)  
(optional)
(required)  
Remember Me?