Skip links
Main content

Calculate ISO 8601 week and year in javascript

Wednesday 22 April 2009 14:18

For one of our projects I needed to be able to calculate the current weeknumber and corresponding year of a given date... in javascript. Not really a big deal, just calculate the number of weeks between the requested date and the 1st of January that year and you're done, right? Wrong!

By Taco van den Broek

Why do we use ISO week numbering?

In our framework (including modules) we use the ISO 8601 standard for week numbering. We've chosen this standard because it is very related to western european workweeks: weeks start on monday and the first week of the year is the first week with a workday in it. Our clients are mostly businesses operating in western europe and therefore this standard is the most obvious choice.

Why this article?

Our framework is built using PHP. In PHP requesting the week and / or year number according to this standard is easy:

// Week and year number using date()
$w = date('W');
$y = date('o');

// Week and year number using strftime()
$w = strftime('%V');
$y = strftime('%G');

But in javascript no built-in methods are available to calculate these values.

ISO 8601 week numbering

This (part of the) standard primarily defines two rules:

  1. Weeks start on monday
  2. The first week of the year is the week with the first thursday of that year

An alternative to the second rule is that the first week of the year is the week with the 4th of January in it. This rule is mostly more convenient in coding.

As a result of this second rule the week with the 1st of January isn't always week number 1. Another result is that some years have 53 weeks instead of 52.

Extending the javascript Date class

To be able to get the week and year numbers in javascript we extend the Date class with two methods: getWeek() and getWeekYear().

Extending a class in javascript can be done by adding properties to the prototype object of that class. In the code below we define Date.prototype.getWeek() and Date.prototype.getYearWeek(), these new methods can be called directly on instances of the Date class:

var today = new Date();
alert("The current week number is: " + today.getWeek());

Date.getWeek()

First, take a look at the code below:

/**
* Get the ISO week date week number
*/
Date.prototype.getWeek = function () {
// Create a copy of this date object
var target = new Date(this.valueOf());

// ISO week date weeks start on monday
// so correct the day number
var dayNr = (this.getDay() + 6) % 7;

// ISO 8601 states that week 1 is the week
// with the first thursday of that year.
// Set the target date to the thursday in the target week
target.setDate(target.getDate() - dayNr + 3);

// Store the millisecond value of the target date
var firstThursday = target.valueOf();

// Set the target to the first thursday of the year
// First set the target to january first
target.setMonth(0, 1);
// Not a thursday? Correct the date to the next thursday
if (target.getDay() != 4) {
target.setMonth(0, 1 + ((4 - target.getDay()) + 7) % 7);
}

// The weeknumber is the number of weeks between the
// first thursday of the year and the thursday in the target week
return 1 + Math.ceil((firstThursday - target) / 604800000); // 604800000 = 7 * 24 * 3600 * 1000
}

The function will calculate the difference in weeks between the first thursday of the year (always week #1) and the thursday in the target week. To do this it will first create a new date object called target and change it so it points at the thursday in the target week. The millisecond value of that date object is then stored. Next, the first thursday of the year is found and the difference in weeks between these two thursdays, plus one, is returned. Because of the ceil any daylight saving differences are ignored.

Date.getWeekYear()

That was the getWeek method, the most important one of the two. The getWeekYear() method uses getWeek() to determine what year to return.

This method is very simple, just return the calendar year of the thursday in the requested week.

/**
* Get the ISO week date year number
*/
Date.prototype.getWeekYear = function ()
{
// Create a new date object for the thursday of this week
var target = new Date(this.valueOf());
target.setDate(target.getDate() - ((this.getDay() + 6) % 7) + 3);

return target.getFullYear();
}

So that's about all you'll need to calculate ISO 8601 year and week numbers in javascript, happy coding!


Optimisation

After reading the site from Dr J R Stockton that Rick recommended in his post I stole a simple trick to make the code a little shorter. Instead of handling the edge cases I first change the date to the thursday of the requested week so the week year number equals the calendar year. I did keep the code more verbose than Stockton did though, just so you understand what exactly happens.


Update (2011-09-28)

Bugs have been fixed. This code is tested for every date between 1970-01-01 and 2100-01-01 (compared with PHP's date('oW') output).

This software is subject to the MIT license: you are free to use it in any way you like as long as it keeps its license.

« Back

Reactions on "Calculate ISO 8601 week and year in javascript"

No posts found

Log in to comment on news articles.