36

I'm looking for a tested solid solution for getting current week of the year for specified date. All I can find are the ones that doesn't take in account leap years or just plain wrong. Does anyone have this type of stuff?

Or even better a function that says how many weeks does month occupy. It is usually 5, but can be 4 (feb) or 6 (1st is sunday and month has 30-31 days in it)

================= UPDATE:

Still not sure about getting week #, but since I figured out it won't solve my problem with calculating how many weeks month occupy, I abandoned it.

Here's a function to find out how many weeks exactly month occupy on the calendar:

getWeeksNum: function(year, month) {
    var daysNum = 32 - new Date(year, month, 32).getDate(),
        fDayO = new Date(year, month, 1).getDay(),
        fDay = fDayO ? (fDayO - 1) : 6,
        weeksNum = Math.ceil((daysNum + fDay) / 7);
    return weeksNum;
}
Max
  • 1,149
  • 3
  • 10
  • 20
  • You should really write this yourself. It's a pretty trivial task. I'm sure google has plenty of answers on how to get leap years. – Trevor Jan 28 '12 at 14:15
  • 4
    I could, but I prefer not to reinvent the wheel, Especially a good tested wheel. – Max Jan 28 '12 at 14:18
  • 3
    Moment.js is a great JS date/time library. Check out the docs -- http://momentjs.com/docs/ -- it has a Week of Year option. You would need to verify how it handles leap year. My experiences with the library have been great so far. – ryanlahue Jan 28 '12 at 19:05
  • 2
    @Max This really is an national issue. Weeks are counted in many different ways in the world. Some countries's calender begins a week at sunday, some others at monday, etc. Even your profile won't tell us, which country's week system you'd like to use within your pages. Location is an issue, which all Stackoverflow users should register in their profile, wheather they were active users or not. These kind of national-dependent questions would be much more easy to answer. – Teemu Jan 28 '12 at 19:45

6 Answers6

31
/**
 * Returns the week number for this date.  dowOffset is the day of week the week
 * "starts" on for your locale - it can be from 0 to 6. If dowOffset is 1 (Monday),
 * the week returned is the ISO 8601 week number.
 * @param int dowOffset
 * @return int
 */
Date.prototype.getWeek = function (dowOffset) {
/*getWeek() was developed by Nick Baicoianu at MeanFreePath: http://www.meanfreepath.com */

    dowOffset = typeof(dowOffset) == 'number' ? dowOffset : 0; //default dowOffset to zero
    var newYear = new Date(this.getFullYear(),0,1);
    var day = newYear.getDay() - dowOffset; //the day of week the year begins on
    day = (day >= 0 ? day : day + 7);
    var daynum = Math.floor((this.getTime() - newYear.getTime() - 
    (this.getTimezoneOffset()-newYear.getTimezoneOffset())*60000)/86400000) + 1;
    var weeknum;
    //if the year starts before the middle of a week
    if(day < 4) {
        weeknum = Math.floor((daynum+day-1)/7) + 1;
        if(weeknum > 52) {
            nYear = new Date(this.getFullYear() + 1,0,1);
            nday = nYear.getDay() - dowOffset;
            nday = nday >= 0 ? nday : nday + 7;
            /*if the next year starts before the middle of
              the week, it is week #1 of that year*/
            weeknum = nday < 4 ? 1 : 53;
        }
    }
    else {
        weeknum = Math.floor((daynum+day-1)/7);
    }
    return weeknum;
};

Usage:

var mydate = new Date(2011,2,3); // month number starts from 0
// or like this
var mydate = new Date('March 3, 2011');
alert(mydate.getWeek());

Source

LBes
  • 3,366
  • 1
  • 32
  • 66
Cheery
  • 16,063
  • 42
  • 57
  • 1
    This doesn't quite seem to be truing out when I compared results using your code against epochconverter.com. Please see this Fiddle and compare your week 1, 2014 vs. epochconverter's week 1. You are off by one? http://jsfiddle.net/q96AM/2/ – mrtsherman Apr 25 '14 at 20:46
  • 1
    Epochconverter shows me the same result - Week 01 = December 30, 2013. It can be off by one day if your week starts on Sunday. – Cheery Apr 26 '14 at 00:24
  • 3
    sorry, I messed up the dates. 2015 is the problem year. Anyways, I debugged the problem. The dowOffset number is running `typeof == 'int'` which should be `typeof == 'number'`. After making the change it works according to ISO 8601 standards. To see the problem, you can edit this fiddle to use 'int' instead of 'number' and you'll see that 2014 has 53 weeks when it should really have 52. This puts all of 2015 off by a week. The problem recurs every decade (2025, 2035, n+10) - http://jsfiddle.net/2PBcS/ – mrtsherman Apr 29 '14 at 20:54
  • 1
    And for background evidence, the MDN docs on typeof - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof as well as the ISO standard 8601 - http://en.wikipedia.org/wiki/ISO_8601#Week_dates – mrtsherman Apr 29 '14 at 20:58
  • 2
    `typeof(dowOffset) == 'int'` will always be `false`, perhaps you meant `typeof dowOffset == 'number'`?. – RobG Mar 25 '19 at 03:50
  • Lol, this function is clearly not in javascript. See the fixed version here: https://gist.github.com/catamphetamine/c0e2f21f1063b11a90f5790eadfcefa4 – catamphetamine Dec 30 '19 at 15:08
  • incorrect for `new Date(2017, 0, 1)` and offset 1. Gives 0 but should be 52 – Robin Dijkhof Aug 18 '22 at 11:24
18

For those looking for a more simple approach;

Date.prototype.getWeek = function() {
  var onejan = new Date(this.getFullYear(),0,1);
  var today = new Date(this.getFullYear(),this.getMonth(),this.getDate());
  var dayOfYear = ((today - onejan + 86400000)/86400000);
  return Math.ceil(dayOfYear/7)
};

Use with:

var today = new Date();
var currentWeekNumber = today.getWeek();
console.log(currentWeekNumber);
alias51
  • 8,178
  • 22
  • 94
  • 166
  • 2
    Not working as expected. `try var today = new Date('2020-10-12T10:45:03.859Z');` Now current week no is `42` but it's showing `41` – Aniket kale Oct 12 '20 at 10:47
  • 1
    For some reason this is giving me week 2 today even though the current week is 1. – Newbyte Jan 07 '21 at 10:55
  • 1
    for typescript, I had to add today.getTime() - onejan.getTime() otherwise it won't compile – heaxyh Nov 10 '22 at 16:09
5

Get week number

Date.prototype.getWeek = function() {
    var dt = new Date(this.getFullYear(),0,1);
    return Math.ceil((((this - dt) / 86400000) + dt.getDay()+1)/7);
};

var myDate = new Date(2013, 3, 25); // 2013, 25 April

console.log(myDate.getWeek());
  • 2
    Not sure if this solution is quite accurate. Here is a Fiddle. It seems to get confused about what is the last week and what is the first week in a given year. http://jsfiddle.net/q96AM/1/ – mrtsherman Apr 25 '14 at 20:41
  • 1
    It is returing 53 for this date var myDate = new Date(2020, 11, 28); // 53 – Abhishek Singh Jan 21 '21 at 12:41
5

Consider using my implementation of "Date.prototype.getWeek", think is more accurate than the others i have seen here :)

Date.prototype.getWeek = function(){
    // We have to compare against the first monday of the year not the 01/01
    // 60*60*24*1000 = 86400000
    // 'onejan_next_monday_time' reffers to the miliseconds of the next monday after 01/01

    var day_miliseconds = 86400000,
        onejan = new Date(this.getFullYear(),0,1,0,0,0),
        onejan_day = (onejan.getDay()==0) ? 7 : onejan.getDay(),
        days_for_next_monday = (8-onejan_day),
        onejan_next_monday_time = onejan.getTime() + (days_for_next_monday * day_miliseconds),
        // If one jan is not a monday, get the first monday of the year
        first_monday_year_time = (onejan_day>1) ? onejan_next_monday_time : onejan.getTime(),
        this_date = new Date(this.getFullYear(), this.getMonth(),this.getDate(),0,0,0),// This at 00:00:00
        this_time = this_date.getTime(),
        days_from_first_monday = Math.round(((this_time - first_monday_year_time) / day_miliseconds));

    var first_monday_year = new Date(first_monday_year_time);

    // We add 1 to "days_from_first_monday" because if "days_from_first_monday" is *7,
    // then 7/7 = 1, and as we are 7 days from first monday,
    // we should be in week number 2 instead of week number 1 (7/7=1)
    // We consider week number as 52 when "days_from_first_monday" is lower than 0,
    // that means the actual week started before the first monday so that means we are on the firsts
    // days of the year (ex: we are on Friday 01/01, then "days_from_first_monday"=-3,
    // so friday 01/01 is part of week number 52 from past year)
    // "days_from_first_monday<=364" because (364+1)/7 == 52, if we are on day 365, then (365+1)/7 >= 52 (Math.ceil(366/7)=53) and thats wrong

    return (days_from_first_monday>=0 && days_from_first_monday<364) ? Math.ceil((days_from_first_monday+1)/7) : 52;
}

You can check my public repo here https://bitbucket.org/agustinhaller/date.getweek (Tests included)

Agustin Haller
  • 521
  • 1
  • 7
  • 24
  • 2
    This ends up not being ISO 8601 compliant. If you look at weeks for year 2015, there are supposed to be 53 week, but this function returns 52. You'll also see that all the weeks are off by one for that year. http://jsfiddle.net/2PBcS/1/ – mrtsherman Apr 30 '14 at 15:04
4

I know this is an old question, but maybe it helps:

http://weeknumber.net/how-to/javascript

// This script is released to the public domain and may be used, modified and
// distributed without restrictions. Attribution not necessary but appreciated.
// Source: https://weeknumber.net/how-to/javascript

// Returns the ISO week of the date.
Date.prototype.getWeek = function() {
  var date = new Date(this.getTime());
  date.setHours(0, 0, 0, 0);
  // Thursday in current week decides the year.
  date.setDate(date.getDate() + 3 - (date.getDay() + 6) % 7);
  // January 4 is always in week 1.
  var week1 = new Date(date.getFullYear(), 0, 4);
  // Adjust to Thursday in week 1 and count number of weeks from date to week1.
  return 1 + Math.round(((date.getTime() - week1.getTime()) / 86400000
                        - 3 + (week1.getDay() + 6) % 7) / 7);
}

// Returns the four-digit year corresponding to the ISO week of the date.
Date.prototype.getWeekYear = function() {
  var date = new Date(this.getTime());
  date.setDate(date.getDate() + 3 - (date.getDay() + 6) % 7);
  return date.getFullYear();
}



Ruan Mendes
  • 90,375
  • 31
  • 153
  • 217
NiMeDia
  • 995
  • 1
  • 15
  • 27
2

/*get the week number by following the norms of ISO 8601*/
function getWeek(dt){
 var calc=function(o){
  if(o.dtmin.getDay()!=1){
   if(o.dtmin.getDay()<=4 && o.dtmin.getDay()!=0)o.w+=1;
   o.dtmin.setDate((o.dtmin.getDay()==0)? 2 : 1+(7-o.dtmin.getDay())+1);
  }
  o.w+=Math.ceil((((o.dtmax.getTime()-o.dtmin.getTime())/(24*60*60*1000))+1)/7);
 },getNbDaysInAMonth=function(year,month){
  var nbdays=31;
  for(var i=0;i<=3;i++){
   nbdays=nbdays-i;
   if((dtInst=new Date(year,month-1,nbdays)) && dtInst.getDate()==nbdays && (dtInst.getMonth()+1)==month  && dtInst.getFullYear()==year)
    break;
  }
  return nbdays;
 };
 if(dt.getMonth()+1==1 && dt.getDate()>=1 && dt.getDate()<=3 && (dt.getDay()>=5 || dt.getDay()==0)){
  var pyData={"dtmin":new Date(dt.getFullYear()-1,0,1,0,0,0,0),"dtmax":new Date(dt.getFullYear()-1,11,getNbDaysInAMonth(dt.getFullYear()-1,12),0,0,0,0),"w":0};
  calc(pyData);
  return pyData.w;
 }else{
  var ayData={"dtmin":new Date(dt.getFullYear(),0,1,0,0,0,0),"dtmax":new Date(dt.getFullYear(),dt.getMonth(),dt.getDate(),0,0,0,0),"w":0},
   nd12m=getNbDaysInAMonth(dt.getFullYear(),12);
  if(dt.getMonth()==12 && dt.getDay()!=0 && dt.getDay()<=3 && nd12m-dt.getDate()<=3-dt.getDay())ayData.w=1;else calc(ayData);
  return ayData.w;
 }
}
alert(getWeek(new Date(2017,01-1,01)));
S.Younes
  • 21
  • 3