Get week of the month
Asked Answered
B

17

31

How can i get the week number of month using javascript / jquery?

For ex.:

First Week: 5th July, 2010. / Week Number = First monday

Previous Week: 12th July, 2010. / Week Number = Second monday

Current Date: 19th July, 2010. / Week Number = Third Monday

Next week: 26th July, 2010. / Week Number = Last monday

Brat answered 19/7, 2010 at 10:43 Comment(4)
Is it just me who thinks most answers here are overly complex or completely wrong for the OP? I think Math.ceil(new Date().getDate() / 7) pretty much gives the nth occurrence of the weekday of given date. Most answers here are talking about week numbers instead of weekday occurrence. For instance, no date can ever be 6th occurrence of weekday (it may indeed fall in the 6th week of that month)Dogcart
This worked well for me. ThanksLiteralism
@Dogcart - Your approach is certainly the cleanest (and bonus: it works!) ThanksEmileemilee
@Dogcart - your answer is correct. Almost everyone else answered a different question: what is the week number of month for some date?Vento
R
-1

function weekAndDay(date) {
    
    var days = ['Sunday','Monday','Tuesday','Wednesday',
                'Thursday','Friday','Saturday'],
        prefixes = ['First', 'Second', 'Third', 'Fourth', 'Fifth'];

    return prefixes[Math.floor(date.getDate() / 7)] + ' ' + days[date.getDay()];

}

console.log( weekAndDay(new Date(2010,7-1, 5)) ); // => "First Monday"
console.log( weekAndDay(new Date(2010,7-1,12)) ); // => "Second Monday"
console.log( weekAndDay(new Date(2010,7-1,19)) ); // => "Third Monday"
console.log( weekAndDay(new Date(2010,7-1,26)) ); // => "Fourth Monday"
console.log( weekAndDay(new Date()) );

Adding the capability to have Last ... may take some more hacking...

Retinol answered 19/7, 2010 at 10:56 Comment(7)
this is perfect for me. Thanks for the solution. I have replaced fifth as last which is same as the repeat event (Monthly) in google calendar.Brat
-1, this does not work. Expected: 3, 7, 7, 7, 7. Actual: 6, 7, 7, 7, 4. Code: var c = {'0':0,'1':0,'2':0,'3':0,'4':0}; for (var i = 1; i <= 31; i++) { c[(0 | new Date(2012, 2, i).getDate() / 7).toString()]++; } console.log(c);Hairdo
this wont work if the month isn't starting with mondayEtruria
code is wrong If Date is new Date(2015,8,7); than return "Second Monday"Homeopathic
@Hairdo @JayShukla @AshishVaghasiya The month is expressed from 0 to 11 so new Date(2015,8,7) is for September 7th of 2015 and not for August. The code works.Sinistrodextral
It doesn't work for many cases using Math.floor(date.getDate() / 7). But works if you replace it by Math.ceil(date.getDate() / 7 - 1). Today, for instance, is the 14, but it's the second Friday of the month, as the Month started on a Saturday.Inefficiency
@EduardoRusso's fix gives the correct result. Should update the solution to prevent further confusionMantellone
H
33

This is an old question, here is my cross-browser solution based on:

  1. Weeks start on Sunday
  2. The first week of a month is the one that contains the first of the month

So in March 2013:

  • Fri 1 Mar is the first day of week 1
  • Sun 3 Mar is the start of week 2
  • Sun 31 Mar is the start of week 6 (and is the only day in the that week)
  • Mon 1 Apr is the first day of week 1 in April.

    Date.prototype.getWeekOfMonth = function(exact) {
        var month = this.getMonth()
            , year = this.getFullYear()
            , firstWeekday = new Date(year, month, 1).getDay()
            , lastDateOfMonth = new Date(year, month + 1, 0).getDate()
            , offsetDate = this.getDate() + firstWeekday - 1
            , index = 1 // start index at 0 or 1, your choice
            , weeksInMonth = index + Math.ceil((lastDateOfMonth + firstWeekday - 7) / 7)
            , week = index + Math.floor(offsetDate / 7)
        ;
        if (exact || week < 2 + index) return week;
        return week === weeksInMonth ? index + 5 : week;
    };
    
    // Simple helper to parse YYYY-MM-DD as local
    function parseISOAsLocal(s){
      var b = s.split(/\D/);
      return new Date(b[0],b[1]-1,b[2]);
    }

    // Tests
    console.log('Date          Exact|expected   not exact|expected');
    [   ['2013-02-01', 1, 1],['2013-02-05', 2, 2],['2013-02-14', 3, 3],
        ['2013-02-23', 4, 4],['2013-02-24', 5, 6],['2013-02-28', 5, 6],
        ['2013-03-01', 1, 1],['2013-03-02', 1, 1],['2013-03-03', 2, 2],
        ['2013-03-15', 3, 3],['2013-03-17', 4, 4],['2013-03-23', 4, 4],
        ['2013-03-24', 5, 5],['2013-03-30', 5, 5],['2013-03-31', 6, 6],
        ['2013-04-01', 1, 1]
    ].forEach(function(test){
      var d = parseISOAsLocal(test[0])
      console.log(test[0] + '        ' + 
      d.getWeekOfMonth(true) + '|' + test[1] + '                  ' +
      d.getWeekOfMonth() + '|' + test[2]); 
    });

You don't need to put it directly on the prototype if you don't want to. In my implementation, 6 means "Last", not "Sixth". If you want it to always return the actual week of the month, just pass true.

EDIT: Fixed this to handle 5 & 6-week months. My "unit tests", feel free to fork: http://jsfiddle.net/OlsonDev/5mXF6/1/.

Hairdo answered 7/3, 2012 at 20:37 Comment(22)
the script returns wrong week date when the month has 5 weeksArkhangelsk
So it does; looks like I made one assumption too many. I'll fix this answer tonight.Hairdo
great answer; changing the second return to this seemed to patch the problem above for me: return week === weeksInMonth ? index + (weeksInMonth-1) : week;Resemblance
This doesn't work as expected. Looking at the fiddle, it says that, for instance, 2/24/13 is the 5th Sunday of the month, but actually, it's the 4th Sunday of the month.Phratry
@Phratry While you're correct 2/24/13 is the 4th Sunday of the month, it's the 5th week of the month. The function's name is getWeekOfMonth(), not getInstanceOfDayInMonth() ... the original question is a little vague so I can see where the confusion may lie. While I'm pretty confident in my function now, I'd have to recommend momentjs.com in favor of it.Hairdo
@Hairdo Are you sure momentjs has a function call for this? Care to point out for us?Tunnel
@Tunnel Out of the box, momentjs doesn't have this function; adding Twix (a useful, officially recognized plugin), you could implement a more readable version of this function. It'd be something like... var a = moment(); var b = moment().startOf('month'); var weekOfMonth = a.twix(b).count('weeks'); This doesn't handle two cases: providing a special return value for "Last" and when a.isSame(b).Hairdo
@Tunnel I created an issue on momentjs's GitHub repo if you'd like to track it.Hairdo
Stealing a portion of the algorithm for calculating the week of the year on Wikipedia got me to 0 | (this.getDate() + 11) / 7Korney
@Hairdo May I ask what exact really means ? What was it there in the first place ?Shir
@Shir Please note the latter part of my answer where I mentioned passing true. Essentially exact indicates whether you want the last week of the month represented to you as a magic number telling you it's the last week or if you want it to be treated the same as every other week in the month.Hairdo
@Hairdo Thanks. Is the index in the fn job is to indicate whether it's 0 based or 1 based index ?Shir
@Shir Yup, you got it.Hairdo
While your approach may be correct (I haven't tested), I believe that the OP wanted the other thing as mentioned in one of the comments above, i.e., instance of weekday in the month. For that, my simple solution would be Math.ceil(new Date().getDate() / 7);. Anyway, I won't mind posting an answer to gather downvotes from some confused souls out there, that too on an inactive post where the OP wouldn't bother clearing out the confusion. Cheers for your efforts on this answer.Dogcart
@Hairdo Is there any other way to get getInstanceOfDayInMonth() instead as CMH mentioned. Could you share function for that?Truda
This is not working as expected. for input ['2020-04-23 18:00:25', '2020-04-26 18:00:25'] I'm expecting something like 4 & 5 respectively. Getting 4 & 6Vigen
@Vigen Re-read my answer. :-) In particular, the bit under the code snippet.Hairdo
Great code, but I think your offsetDate calculation should be: `offsetDate = this.getDate() - firstWeekday + 1Sling
@HomunculusReticulli I don't think you tested your suggestion; just using it on the "unit test" dates in the answer yields 0 passing tests.Hairdo
@Hairdo actually, I responded to your comment - looking at my code suggestion. I'm just starting out with JS. Care to explain that statement? I don't understand why you would add firstWeekday to the current date ?Sling
Getting invalid week number for date: "2021-02-28"Psychosomatic
@PradipBhuvani No, you're not -- 6 is expected. If you want 5, pass true to the function. Please re-read my answer; in particular, the bit under the code snippet.Hairdo
O
11

Having struggle with this topic too - thanks to Olson.dev! I've shortened his function a little bit, if somebody is interessted:

// returns week of the month starting with 0
Date.prototype.getWeekOfMonth = function() {
  var firstWeekday = new Date(this.getFullYear(), this.getMonth(), 1).getDay();
  var offsetDate = this.getDate() + firstWeekday - 1;
  return Math.floor(offsetDate / 7);
}

update: if you need a localized version - you have to tweak the firstWeekday variable

// german version - week starts with monday
Date.prototype.getWeekOfMonth = function() {
  var firstWeekday = new Date(this.getFullYear(), this.getMonth(), 1).getDay() - 1;
  if (firstWeekday < 0) firstWeekday = 6;
  var offsetDate = this.getDate() + firstWeekday - 1;
  return Math.floor(offsetDate / 7);
}
Orang answered 16/3, 2016 at 12:53 Comment(3)
I found this only works with offsetDate = this.getDate() + firstWeekday - 2, otherwise it returns the wrong value for SundayForetaste
I think what you need is like a localized variant of the function. I've updated the code with another example - maybe this helps.Orang
Olso.dev version did not work for me in April 2020.. This works brilliantly, thanks.Vigen
P
9

I think this works. It returns the week of the month, starting at 0:

var d = new Date();
var date = d.getDate();
var day = d.getDay();

var weekOfMonth = Math.ceil((date - 1 - day) / 7);
Pyrography answered 22/4, 2014 at 19:40 Comment(3)
Short and sweet. Not sure why this isn't upvoted more!Powwow
good answer. just to add +1 in each weekBoschbok
will it work if start day of week is Monday?Unidirectional
S
4
function getWeekOfMonth(date) {
  const startWeekDayIndex = 1; // 1 MonthDay 0 Sundays
  const firstDate = new Date(date.getFullYear(), date.getMonth(), 1);
  const firstDay = firstDate.getDay();

  let weekNumber = Math.ceil((date.getDate() + firstDay) / 7);
  if (startWeekDayIndex === 1) {
    if (date.getDay() === 0 && date.getDate() > 1) {
      weekNumber -= 1;
    }

    if (firstDate.getDate() === 1 && firstDay === 0 && date.getDate() > 1) {
      weekNumber += 1;
    }
  }
  return weekNumber;
}

I hope this works Tested until 2025

Suzerainty answered 22/5, 2018 at 21:37 Comment(0)
N
3

I think you want to use weekOfMonth so it will give 1-4 or 1-5 week of month. I solved the same problem with this:

var dated = new Date();
var weekOfMonth = (0 | dated.getDate() / 7)+1;
Nozicka answered 6/1, 2017 at 9:13 Comment(0)
T
2
week_number = 0 | new Date().getDate() / 7
Torino answered 7/4, 2013 at 19:28 Comment(1)
for date 2016-08-07, it gives week number as 1. And for for date 2016-08-08 also, it gives week number as 1? is this correct?Skin
V
2

This is a few years on, but I've needed to use this functionality recently and, for certain dates in years 2016/2020 (such as January 31st), none of the code here works.

It's not the most efficient by any means, but hopefully this helps someone out as it's the only thing I could get working for those years along with every other year.

Date.prototype.getWeekOfMonth = function () {
    var dayOfMonth = this.getDay();
    var month = this.getMonth();
    var year = this.getFullYear();
    var checkDate = new Date(year, month, this.getDate());
    var checkDateTime = checkDate.getTime();
    var currentWeek = 0;

    for (var i = 1; i < 32; i++) {
        var loopDate = new Date(year, month, i);

        if (loopDate.getDay() == dayOfMonth) {
            currentWeek++;
        }

        if (loopDate.getTime() == checkDateTime) {
            return currentWeek;
        }
    }
};
Vibrato answered 30/6, 2015 at 9:3 Comment(2)
Partially working, for instance, 2015-11-30 is in sixth week but your code is showing in fifth week (week start with Monday).Intramural
I know it's been 7 months since you posted this but I tested your dates 01/31/2016 and 01/31/2020 with my answer's function and got the expected results (2016 = 6|6, 2015 = 5|6 ... meaning exactly 6th week, also "Last week" (6) for 2016 and exactly 5th week, also "Last week" (6) for 2020).Hairdo
B
2
import getWeekOfMonth from 'date-fns/getWeekOfMonth'
...
let weekOfMonth = getWeekOfMonth(new Date())

https://date-fns.org/v2.0.0-alpha.9/docs/getWeekOfMonth

Behaviorism answered 15/12, 2020 at 8:52 Comment(0)
I
2

None of the previous solutions included the "Last" on the response and I was able to do it by checking the next occurrence of the same day of the week and checking if it's still on this month.

The accepted answer fails in many cases (I tested it with today's date - 2021-05-14 - and it returned "Third Friday" when it's actually the second).

This code below was tested even with April 2017 (a rare case of a month with 6 weeks).

April 2017 - month with 6 weeks

/**
 * Get the week number of the month, from "First" to "Last"
 * @param {Date} date 
 * @returns {string}
 */
 function weekOfTheMonth(date) {
  const day = date.getDate()
  const weekDay = date.getDay()
  let week = Math.ceil(day / 7)
  
  const ordinal = ['First', 'Second', 'Third', 'Fourth', 'Last']
  const weekDays  = ['Sunday','Monday','Tuesday','Wednesday', 'Thursday','Friday','Saturday']
  

  // Check the next day of the week and if it' on the same month, if not, respond with "Last"
  const nextWeekDay = new Date(date.getTime() + (1000 * 60 * 60 * 24 * 7))
  if (nextWeekDay.getMonth() !== date.getMonth()) {
    week = 5
  }
  
  return `${ordinal[week - 1]} ${weekDays[weekDay]}`
}

const days = [
  new Date('2021-05-14'),
  new Date('26 July 2010'),
  new Date('5 July 2010'),
  new Date('12 July 2010'),
  new Date('22 April 2017'),
  new Date('29 April 2017'),
]

for (let i = 0; i < days.length; i += 1) {
  const d = days[i]
  console.log(d, weekOfTheMonth(d))
}
Inefficiency answered 14/5, 2021 at 13:57 Comment(0)
I
0

This is nothing natively supported.

You could roll your own function for this, working from the first day of the month

var currentDate = new Date();
var firstDayOfMonth = new Date( currentDate.getFullYear(), currentDate.getMonth(), 1 );

And then getting the weekday of that date:

var firstWeekday = firstDayOfMonth.getDay();

... which will give you a zero-based index, from 0-6, where 0 is Sunday.

Indecorum answered 19/7, 2010 at 10:50 Comment(0)
B
0

I was just able to figure out a easier code for calculate the number of weeks for a given month of an year ..

y == year for example { 2012 } m == is a value from { 0 - 11 }

function weeks_Of_Month( y, m ) {
    var first = new Date(y, m,1).getDay();      
    var last = 32 - new Date(y, m, 32).getDate(); 

    // logic to calculate number of weeks for the current month
    return Math.ceil( (first + last)/7 );   
}
Brat answered 28/3, 2013 at 8:34 Comment(0)
Z
0
function weekNumberForDate(date){

    var janOne = new Date(date.getFullYear(),0,1);
    var _date = new Date(date.getFullYear(),date.getMonth(),date.getDate());
    var yearDay = ((_date - janOne + 1) / 86400000);//60 * 60 * 24 * 1000
    var day = janOne.getUTCDay();
    if (day<4){yearDay+=day;}
    var week = Math.ceil(yearDay/7);

   return week;
}

Apparently the first week of the year is the week that contains that year's first Thursday.

Without calculating the UTCDay, the returned week was one week shy of what it should have been. Not confident this can't be improved, but seems to work for now.

Zygophyte answered 10/11, 2015 at 9:59 Comment(0)
T
0
function getWeekOfMonth(date) {

  var nth = 0; // returning variable.
  var timestamp = date.getTime(); // get UTC timestamp of date.
  var month = date.getMonth(); // get current month.
  var m = month; // save temp value of month.

  while( m == month ) {  // check if m equals our date's month.
    nth++; // increment our week count.
    // update m to reflect previous week (previous to last value of m).
    m = new Date(timestamp - nth * 604800000).getMonth();
  }

  return nth;

}
Torin answered 15/2, 2017 at 23:23 Comment(0)
B
0

After reading all the answers I figured out a way that use less CPU than the others and work for every day of every month of every year. Here is my code:

function getWeekInMonth(year, month, day){

    let weekNum = 1; // we start at week 1

    let weekDay = new Date(year, month - 1, 1).getDay(); // we get the weekDay of day 1
    weekDay = weekDay === 0 ? 6 : weekDay-1; // we recalculate the weekDay (Mon:0, Tue:1, Wed:2, Thu:3, Fri:4, Sat:5, Sun:6)

    let monday = 1+(7-weekDay); // we get the first monday of the month

    while(monday <= day) { //we calculate in wich week is our day
        weekNum++;
        monday += 7;
    }

    return weekNum; //we return it
}

I hope this can help.

Bedew answered 29/11, 2017 at 12:29 Comment(0)
C
0

Please try below function.This one is considering week start date as Monday and week end date as Sunday.

getWeekNumber(date) {
    var monthStartDate =new Date(new Date().getFullYear(), new 
         Date().getMonth(), 1);
    monthStartDate = new Date(monthStartDate);
    var day = startdate.getDay();
    date = new Date(date);
    var date = date.getDate();
    return Math.ceil((date+ day-1)/ 7);
}
Cirsoid answered 10/5, 2018 at 5:49 Comment(0)
L
0

You just need this:

Math.ceil(new Date().getDate() / 7)
Leucippus answered 17/6, 2022 at 6:26 Comment(1)
This only works if all months start on sunday (which they don't)Boudreau
R
-1

function weekAndDay(date) {
    
    var days = ['Sunday','Monday','Tuesday','Wednesday',
                'Thursday','Friday','Saturday'],
        prefixes = ['First', 'Second', 'Third', 'Fourth', 'Fifth'];

    return prefixes[Math.floor(date.getDate() / 7)] + ' ' + days[date.getDay()];

}

console.log( weekAndDay(new Date(2010,7-1, 5)) ); // => "First Monday"
console.log( weekAndDay(new Date(2010,7-1,12)) ); // => "Second Monday"
console.log( weekAndDay(new Date(2010,7-1,19)) ); // => "Third Monday"
console.log( weekAndDay(new Date(2010,7-1,26)) ); // => "Fourth Monday"
console.log( weekAndDay(new Date()) );

Adding the capability to have Last ... may take some more hacking...

Retinol answered 19/7, 2010 at 10:56 Comment(7)
this is perfect for me. Thanks for the solution. I have replaced fifth as last which is same as the repeat event (Monthly) in google calendar.Brat
-1, this does not work. Expected: 3, 7, 7, 7, 7. Actual: 6, 7, 7, 7, 4. Code: var c = {'0':0,'1':0,'2':0,'3':0,'4':0}; for (var i = 1; i <= 31; i++) { c[(0 | new Date(2012, 2, i).getDate() / 7).toString()]++; } console.log(c);Hairdo
this wont work if the month isn't starting with mondayEtruria
code is wrong If Date is new Date(2015,8,7); than return "Second Monday"Homeopathic
@Hairdo @JayShukla @AshishVaghasiya The month is expressed from 0 to 11 so new Date(2015,8,7) is for September 7th of 2015 and not for August. The code works.Sinistrodextral
It doesn't work for many cases using Math.floor(date.getDate() / 7). But works if you replace it by Math.ceil(date.getDate() / 7 - 1). Today, for instance, is the 14, but it's the second Friday of the month, as the Month started on a Saturday.Inefficiency
@EduardoRusso's fix gives the correct result. Should update the solution to prevent further confusionMantellone

© 2022 - 2024 — McMap. All rights reserved.