2006-07-27 - ISO8601 Week Number Format

Introduction

The ISO8601 defines how to calculate the week number from a gregorian date. The week number is used in industry or any important organisations to manage projects and ressources. You can find more information about this format on wikipedia .

Update 02/12/2008: Thanks to Guido's bug fixes. You can see a demo page using this code here

Implementation

I come up with my own implementation, as I cannot find any clean JS code and reliable code to generate the week number. The JS code is based on the algorythm defined by Rick McCarty .

/**
* Author : Thomas Rabaix
*
* return the Week Number of a gregorian date using the ISO 8601 format
* Algorithm from http://personal.ecu.edu/mccartyr/ISOwdALG.txt , Rick McCarty, 1999
*
* ISO 8601 specifies that Week 01 of the year is the week containing
* the first Thursday; Monday is Weekday 1, Sunday is Weekday 7;
* WeekNumber requires two digits (W01, W02, etc.; "W" is optional)
*/
var isoHelper = {
getWeekNumber: function(date) {
// 1. Convert input to Y M D
var Y = date.getFullYear();
var M = date.getMonth();
var D = date.getDay();

// 4. Find the DayOfYearNumber for Y M D
var DayOfYearNumber = isoHelper.findDayOfYearNumber(date);

// 5. Find the Jan1Weekday for Y (Monday=1, Sunday=7)
var Jan1Weekday = isoHelper.findJan1Weekday(date);

// 6. Find the Weekday for Y M D
var WeekDay = isoHelper.findDayWeek(date);

// 7. Find if Y M D falls in YearNumber Y-1, WeekNumber 52 or 53
var YearNumber = Y;
var WeekNumber = 0;
if((DayOfYearNumber <= (8 - Jan1Weekday)) && (Jan1Weekday > 4)) {
YearNumber = Y - 1
if((Jan1Weekday == 5) || (Jan1Weekday == 6 && isoHelper.isLeapYear(date))) {
WeekNumber = 53;
} else {
WeekNumber = 52;
}
}

// 8. Find if Y M D falls in YearNumber Y+1, WeekNumber 1
if(YearNumber == Y) {
var I;
if(isoHelper.isLeapYear(date)) {
I = 366;
} else {
I = 365
}

if ((I - DayOfYearNumber) < (4 - WeekDay)) {
YearNumber = Y + 1;
WeekNumber = 1;
}
}

// 9. Find if Y M D falls in YearNumber Y, WeekNumber 1 through 53
if(YearNumber == Y) {
var J;
J = DayOfYearNumber + (7 - WeekDay) + (Jan1Weekday - 1)
WeekNumber = J / 7;
if(Jan1Weekday > 4 ) {
WeekNumber -= 1;
}
}

return WeekNumber;
},
isLeapYear: function(date) {
if ((Y % 4) == 0 && (Y % 100) != 0) {
return true;
}
if((Y % 400) == 0) {
return true;
}
return false;
},
findDayOfYearNumber: function(date) {
var months = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];

var day = date.getDate() + months[date.getMonth()];

if(isoHelper.isLeapYear(date) && date.getMonth() > 1) {
day++;
}

return day;
},
findJan1Weekday: function(date) {
var d = new Date(date.getFullYear(), 0, 1);
return isoHelper.findDayWeek(d);
},
findDayWeek: function (date) {
var WeekDay = date.getDay();
if(WeekDay == 0) {
WeekDay = 7;
}

return WeekDay;
}
}

Usage

var startDate = new Date(); // get the current date
var numWeek = isoHelper.getWeekNumber(startDate);