Skip to content

Instantly share code, notes, and snippets.

@markthiessen
Last active February 19, 2025 12:10
Show Gist options
  • Select an option

  • Save markthiessen/3883242 to your computer and use it in GitHub Desktop.

Select an option

Save markthiessen/3883242 to your computer and use it in GitHub Desktop.
JavaScript - get weeks in a month as array of start and end days
//note: month is 0 based, just like Dates in js
function getWeeksInMonth(year, month) {
const weeks = [],
firstDate = new Date(year, month, 1),
lastDate = new Date(year, month + 1, 0),
numDays = lastDate.getDate();
let dayOfWeekCounter = firstDate.getDay();
for (let date = 1; date <= numDays; date++) {
if (dayOfWeekCounter === 0 || weeks.length === 0) {
weeks.push([]);
}
weeks[weeks.length - 1].push(date);
dayOfWeekCounter = (dayOfWeekCounter + 1) % 7;
}
return weeks
.filter((w) => !!w.length)
.map((w) => ({
start: w[0],
end: w[w.length - 1],
dates: w,
}));
}
exports.getWeeksInMonth = getWeeksInMonth;
const getWeeksInMonth = require("./getWeeksInMonth").getWeeksInMonth;
describe("getWeeksInMonth", () => {
test("June 2019 (starts on Saturday)", () => {
const weeks = getWeeksInMonth(2019, 5);
expect(weeks.length).toBe(6);
expect(weeks[0].start).toBe(1);
expect(weeks[0].end).toBe(1);
});
test("Feb 2021 (starts on Monday)", () => {
const weeks = getWeeksInMonth(2021, 1);
expect(weeks.length).toBe(5);
expect(weeks[0].start).toBe(1);
expect(weeks[0].end).toBe(6);
expect(weeks[4].start).toBe(28);
expect(weeks[4].end).toBe(28);
});
test("Aug 2021 (starts on Sunday)", () => {
const weeks = getWeeksInMonth(2021, 7);
expect(weeks.length).toBe(5);
expect(weeks[0].start).toBe(1);
expect(weeks[0].end).toBe(7);
expect(weeks[4].start).toBe(29);
expect(weeks[4].end).toBe(31);
});
});
@ecorvo

ecorvo commented Nov 21, 2016

Copy link
Copy Markdown

Thanks!

@TheGitPanda

TheGitPanda commented Jun 7, 2017 •

Copy link
Copy Markdown

Thanks for this works perfect, except I had to add this line after end = end + 7:

end = start === 1 && end === 8 ? 1 : end;

Without it, months where they start on the last day of the week were returning {start:1, end: 8} for first week : )

@itzikbenh

Copy link
Copy Markdown

If you want to support starting with Monday, I believe this should work.

function getWeeksStartAndEndInMonth(month, year, start) {
    let weeks = [],
        firstDate = new Date(year, month, 1),
        lastDate = new Date(year, month + 1, 0),
        numDays = lastDate.getDate();

    let start = 1;
    let end = 7 - firstDate.getDay();
    if (start === 'monday') {
        if (firstDate.getDay() === 0) {
            end = 1;
        } else {
            end = 7 - firstDate.getDay() + 1;
        }
    }
    while (start <= numDays) {
        weeks.push({start: start, end: end});
        start = end + 1;
        end = end + 7;
        end = start === 1 && end === 8 ? 1 : end;
        if (end > numDays) {
            end = numDays;
        }
    }
    return weeks;
}

@itzikbenh

itzikbenh commented Oct 9, 2017 •

Copy link
Copy Markdown

This one will allow you to start from any day of the week.

function endFirstWeek(firstDate, firstDay) {
    if (! firstDay) {
        return 7 - firstDate.getDay();
    }
    if (firstDate.getDay() < firstDay) {
        return firstDay - firstDate.getDay();
    } else {
        return 7 - firstDate.getDay() + firstDay;
    }
}

function getWeeksStartAndEndInMonth(month, year, start) {
    let weeks = [],
        firstDate = new Date(year, month, 1),
        lastDate = new Date(year, month + 1, 0),
        numDays = lastDate.getDate();

    let start = 1;
    let end = endFirstWeek(firstDate, 2);
    while (start <= numDays) {
        weeks.push({start: start, end: end});
        start = end + 1;
        end = end + 7;
        end = start === 1 && end === 8 ? 1 : end;
        if (end > numDays) {
            end = numDays;
        }
    }
    return weeks;
}

@Chriskuang

Copy link
Copy Markdown

thks

@leorcvargas

Copy link
Copy Markdown

Thank you! This are really useful for me. <3

@ghidhawidhekra

ghidhawidhekra commented Feb 13, 2018 •

Copy link
Copy Markdown

Thank you for the Share! Could you please add week number too? @itzikbenh

ghost commented Apr 15, 2018

Copy link
Copy Markdown

@itzikbenh solution worked out best.

@BorisTB

BorisTB commented Jun 18, 2018 •

Copy link
Copy Markdown

@itzikbenh why is there "start" in arguments and then you define it again with "let start = 1" ? Not sure how you made that work

@NerdGr8

NerdGr8 commented Jul 11, 2018 •

Copy link
Copy Markdown
function getWeeksStartAndEndInMonth(month, year, _start) {
    let monthNames = ["January", "February", "March", "April", "May", "June",
        "July", "August", "September", "October", "November", "December"
        ],
        d = new Date();
    console.log("The current month is " + monthNames[d.getMonth()]);
    let weeks = [],
        firstDate = new Date(year, month, 1),
        lastDate = new Date(year, month + 1, 0),
        numDays = lastDate.getDate();
    var c = Date()
    let start = 1;
    let end = 7 - firstDate.getDay();
    if (_start == 'monday') {
        if (firstDate.getDay() === 0) {
            end = 1;
        } else {
            end = 7 - firstDate.getDay() + 1;
        }
    }
    while (start <= numDays) {
        var businessWeekEnd = end-2
        if(businessWeekEnd > 0){
            if(businessWeekEnd > start){
                weeks.push({start: start, end: businessWeekEnd});
            }
            else{
                //Check for last day else end date is within 5 days of the week.
                weeks.push({start: start, end: end});
            }
        }
        start = end + 1;
        end = end + 7;
        end = start === 1 && end === 8 ? 1 : end;
        if (end > numDays) {
            end = numDays;
        }
    }

    weeks.forEach(week => {
        var _s = parseInt(week.start, 10)+1,
            _e = parseInt(week.end,10)+1;
        console.log(new Date(year, month, _s).toJSON().slice(0,10).split('-').reverse().join('/') + " - " + new Date(year, month, _e).toJSON().slice(0,10).split('-').reverse().join('/'));
        console.log(((_e-_s)+1)*8)
    });
    return weeks;
}
console.table(getWeeksStartAndEndInMonth(6, 2018, 'monday'));

@anantl05

Copy link
Copy Markdown

Thanks a ton!

@kingqi

kingqi commented Dec 3, 2018

Copy link
Copy Markdown

Thanks a lot, here is some code to get full weeks ( like first week will be like '26-2'), also allow you to start from any day of the week.
Any suggestion will be appreciated

// _start is 0 based
getFullWeeksStartAndEndInMonth = (month, year, _start) => {
    let weeks = [],
      firstDate = new Date(year, month, 1),
      lastDate = new Date(year, month + 1, 0),
      numDays = lastDate.getDate()

    let start = 1
    let end = 7 - firstDate.getDay()
    if (firstDate.getDay() === _start) {
      end = 7
    } else {
      preMonthEndDay = new Date(year, month, 0)
      start = preMonthEndDay.getDate() + 1 - firstDate.getDay() + _start
      end = 7 - firstDate.getDay() + _start
      weeks.push({ start: start, end: end })
      start = end + 1
      end = end + 7
    }
    while (start <= numDays) {
      weeks.push({ start: start, end: end })
      start = end + 1
      end = end + 7
      if (end > numDays) {
        end = end - numDays + _start
        weeks.push({ start: start, end: end })
        break
      }
    }
    return weeks
  }

@abcx

abcx commented Mar 15, 2019 •

Copy link
Copy Markdown

This TypeScript function returns date ranges for all weeks in given month:

    getWeeksInMonth(year: number, month: number) {

        const weeks = [];
        const firstDay: Date = new Date(year, month, 1);
        const lastDay: Date = new Date(year, month + 1, 0);
        const daysInMonth: number = lastDay.getDate();
        let dayOfWeek: number = firstDay.getDay();
        let start: number;
        let end: number;

        for (let i = 1; i < daysInMonth + 1; i++) {

            if (dayOfWeek === 0 || i === 1) {
                start = i;
            }

            if (dayOfWeek === 6 || i === daysInMonth) {

                end = i;

                if (start !== end) {

                    weeks.push({
                        start: start,
                        end: end
                    });
                }
            }

            dayOfWeek = new Date(year, month, i).getDay();
        }

        return weeks;
    }

Usage:

getWeeksInMonth(2019, 2);

Result for March 2019:

0: {start: 1, end: 3}
1: {start: 4, end: 10}
2: {start: 11, end: 17}
3: {start: 18, end: 24}
4: {start: 25, end: 31}

@junreyd

junreyd commented Jun 20, 2019 •

Copy link
Copy Markdown

Very helpful.

@baj9032

baj9032 commented Aug 17, 2019

Copy link
Copy Markdown

Thank you very useful.

@infomed92

Copy link
Copy Markdown

Hi abcx,
your function is not bad BUT it is not working correctly when we put year=2018 and month=Avril or July.
For example, result for Avril 2018 :
0: {start: 2, end: 8}
1: {start: 9, end: 15}
2: {start: 16, end: 22}
3: {start: 23, end: 29}

@infomed92

infomed92 commented Oct 25, 2019 •

Copy link
Copy Markdown

We should have for Avril 2018 :
0: {start: 1, end: 1}
1: {start: 2, end: 8}
2: {start: 9, end: 15}
3: {start: 16, end: 22}
4: {start: 23, end: 29}
5: {start: 30, end: 30}

@panchihpeng

Copy link
Copy Markdown

I used dayjs to write it. dayjs
It works !

const getWeekMonth = (year, month) => {
  const firstDay = dayjs(`${year}-${month}`).startOf('month').format('d')

  let startDay
  if (firstDay === 1) {
    startDay = dayjs(`${year}-${month}`).format('YYYY-MM-DD')
  } else {
    const diffDays = (8 - firstDay) % 7
    startDay = dayjs(`${year}-${month}`).startOf('month').add(diffDays, 'days').format('YYYY-MM-DD')
  }

  const lastDay = dayjs(`${year}-${month}`).endOf('month').format('d')

  let endDay
  if (lastDay === 0) {
    endDay = dayjs(`${year}-${month}`).endOf('month').format('YYYY-MM-DD')
  } else {
    const lastDiffDays = 6 - lastDay
    endDay = dayjs(`${year}-${month}`).startOf('month').add(1, 'month').add(lastDiffDays, 'days').format('YYYY-MM-DD')
  }

  const weeks = (dayjs(endDay).diff(dayjs(startDay), 'days') + 1) / 7

  const weekList = []
  for (let i = 1; i <= weeks; i++) {
    weekList.push({
      weekName: `第${i}周`,
      num: i,
      startDay,
      endDay: dayjs(startDay).add(6, 'days').format('YYYY-MM-DD'),
      range: `${dayjs(startDay).format('MM-DD')}~${dayjs(startDay).add(6, 'days').format('MM-DD')}`
    })
    startDay = dayjs(startDay).add(7, 'days').format('YYYY-MM-DD')
  }
  return weekList
}

@gktgautam

gktgautam commented Jan 19, 2020 •

Copy link
Copy Markdown

If you want to support starting with Monday,
I believe this TypeScript function should work best.

getWeeksInMonth(year: number, month: number) { const daysName = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
const weeks=[];      
const  lastDate = new Date(year, month + 1, 0); 

let start: number=0;
let end: number; 

for (let i = 1; i < lastDate.getDate()+1; i++) {         
  if (daysName[Number(new Date(year, month, i).getDay())] =="Sunday" || i == lastDate.getDate()) {
    end= i;
    weeks.push({
        start:start+1,
        end:end
      }); 
      start = i;           
   }
 }         
 console.log(weeks);  }`

@brunolkatz

Copy link
Copy Markdown

I make this for get array of weeks:

function getWeeksStartAndEndInMonth(_month: number, _year: number, returnDate: boolean = false) {
    const lastDay = new Date(_year, _month + 1, 0);
    let weeks: Array<{start: number, end: number}> = [];
    let _days = [];
    for (let _day = 1; _day <= lastDay.getDate(); _day++){
        let _thisDay = new Date(_year, _month, _day);
        _days.push(returnDate ? _thisDay : _day);
        if(_thisDay.getDay() === 6){
            weeks.push({start: _days[0], end: _days[_days.length-1]});
            _days = [];
        }else if(_thisDay.getDate() === lastDay.getDate()){
            weeks.push({start: _days[0], end: _days[_days.length-1]});
        }
    }
    return weeks;
}

for(let i = 0; i <= 11; i++){
    let _month = getWeeksStartAndEndInMonth(i,2020);
    console.log(_month);
}

@bedirhanyildirim

bedirhanyildirim commented Nov 27, 2020 •

Copy link
Copy Markdown

If the week starts with 'Monday' as index 1:

// note: month is in range 0-11
function getFullWeeksStartAndEndInMonth (month, year) {
    let weeks = [],
        firstDate = new Date(year, month, 1),
        lastDate = new Date(year, month + 1, 0),
        numDays = lastDate.getDate()

    let start = 1
    let end
    if (firstDate.getDay() === 1) {
        end = 7
    } else if (firstDate.getDay() === 0) {
        let preMonthEndDay = new Date(year, month, 0)
        start = preMonthEndDay.getDate() - 6 + 1
        end = 1
    } else {
        let preMonthEndDay = new Date(year, month, 0)
        start = preMonthEndDay.getDate() + 1 - firstDate.getDay() + 1
        end = 7 - firstDate.getDay() + 1
        weeks.push({
            start: start,
            end: end
        })
        start = end + 1
        end = end + 7
    }
    while (start <= numDays) {
        weeks.push({
            start: start,
            end: end
        });
        start = end + 1;
        end = end + 7;
        end = start === 1 && end === 8 ? 1 : end;
        if (end > numDays && start <= numDays) {
            end = end - numDays
            weeks.push({
                start: start,
                end: end
            })
            break
        }
    }
    return weeks
}

@Sagargalande

Sagargalande commented Feb 1, 2021 •

Copy link
Copy Markdown

This code will start first day of month

Week start day Monday and end day Sunday

Last week end is month end day

function getWeeksStartAndEndInMonth(month, year) {
  let weeks = [],
      firstDate = new Date(year, month, 1),
      lastDate = new Date(year, month , 0),
      numDays = lastDate.getDate();

   start = 1;
  let end = GetfirstWeekEnd(month,year).getDate();
  while (start <= numDays) {
      weeks.push({start: start, end: end});
      start = end + 1;
      end = end + 7;
      end = start === 1 && end === 8 ? 1 : end;
      if (end > numDays) {
          end = numDays;
      }
  }
  return weeks;
  }

 function GetfirstWeekEnd(month,year) {
      var firstDay= new Date(year + "-" + month + "-" + 1);
      var first = firstDay;
      const lastDay = new Date(year, month, 0);
      const daysInMonth = lastDay.getDate();
      let dayOfWeek = firstDay.getDay();
      var endday="";
      var startCount = dayOfWeek;
      if (startCount != 0) {
           endday = new Date( firstDay.setDate( firstDay.getDate() + (7-dayOfWeek)));
      }
      else {
          endday = new Date(firstDay.setDate( firstDay.getDate() + 1));

      }
      return endday;
  } 
  
  function endFirstWeek(firstDate, firstDay) {
  if (! firstDay) {
      return 7 - firstDate.getDay();
  }
  if (firstDate.getDay() < firstDay) {
      return firstDay - firstDate.getDay();
  } else {
      return 7 - firstDate.getDay() + firstDay;
  }
}

### ### ### ###

Input :
getWeeksStartAndEndInMonth(1, 2021)
here is output
0: {start: 1, end: 3}
1: {start: 4, end: 10}
2: {start: 11, end: 17}
3: {start: 18, end: 24}
4: {start: 25, end: 31}

@pereira-a

Copy link
Copy Markdown

If you want a function to return a month's week based on business days this shall work:

function getWeeksInMonth(year: number, month: number) {
        const weeks = [],
            firstDate = new Date(year, month, 1),
            lastDate = new Date(year, month + 1, 0),
            numDays = lastDate.getDate();
        
        let offset = 0;

        if(firstDate.getDay() === 0) offset = 1;
        else if(firstDate.getDay() === 6) offset = 2;

        let start = 1 + offset;
        let end: number;

        if(offset === 0) end = 5 - firstDate.getDay() + 1;
        else end = 5 - start + 1 + (offset * 2);

        while(start <= numDays) {
            weeks.push({start: start, end: end});
            start = end + 3;
            end = end + 7;
            end = start === 1 && end === 8 ? 1 : end;
            if(end > numDays) end = numDays;
        }

        return weeks;
}

Results for Oct 2020:
image

Results for Feb 2020:
image

Results for March 2020:
image

@suryavi

suryavi commented Jul 19, 2022

Copy link
Copy Markdown

getWeekOfMonth
Screenshot (219)

@dllsystem

dllsystem commented Jan 24, 2024 •

Copy link
Copy Markdown

/**

  • It takes a year and a month as arguments, and returns an array of objects, each object containing
  • the start and end dates of the week, and an array of all the dates in that week
  • @PARAM year - The year of the month you want to get the weeks for.
  • @PARAM month - The month you want to get the weeks for.
  • @returns An array of objects.
    */

function getWeeksInMonth(year, month) {
const weeks = []

let firstDate = new Date(year, month, 1)
let lastDate = new Date(year, month + 1, 0)
let numDays = lastDate.getDate()

let dayOfWeekCounter = firstDate.getDay()

for (let date = 1; date <= numDays; date++) {
if (dayOfWeekCounter === 0 || weeks.length === 0) {
weeks.push([])
}
weeks[weeks.length - 1].push(date)
dayOfWeekCounter = (dayOfWeekCounter + 1) % 7
}

/* This is to add the last week of the previous month to the first week of the current month. */
if (weeks[0].length < 7) {
const beforeIndex1 = addMonth(year, month - 1, 1)
const indexRefactor = [...beforeIndex1, ...weeks[0]]
weeks[0] = indexRefactor
}

/* This is to add the first week of the next month to the last week of the current month. */
if (weeks[weeks.length - 1].length < 7) {
const afterIndex1 = addMonth(year, month + 1, 0)
const indexRefactor = [...weeks[weeks.length - 1], ...afterIndex1]
weeks[weeks.length - 1] = indexRefactor
}

return weeks
.filter((w) => !!w.length)
.map((w) => ({
start: w[0],
end: w[w.length - 1],
dates: w,
}))
}

/**

  • It takes a year, month, and flag, and returns the first or last week of the month, depending on the flag
  • @PARAM year - the year of the month you want to get
  • @PARAM month - The month you want to get the first or last week of.
  • @PARAM flag - 0 for first week, 1 for last week, 2 for all weeks
  • @returns An array of arrays.
    */

const addMonth = (year, month, flag) => {
const weeks = [],
firstDate = new Date(year, month, 1),
lastDate = new Date(year, month + 1, 0),
numDays = lastDate.getDate()

let dayOfWeekCounter = firstDate.getDay()
for (let date = 1; date <= numDays; date++) {
if (dayOfWeekCounter === 0 || weeks.length === 0) {
weeks.push([])
}
weeks[weeks.length - 1].push(date)
dayOfWeekCounter = (dayOfWeekCounter + 1) % 7
}
if (flag === 0) {
return weeks[0]
}
if (flag === 1) {
return weeks[weeks.length - 1]
}
return []
}

console.table(getWeeksInMonth(2024, 0))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment