Skip to content

Instantly share code, notes, and snippets.

@markthiessen
Last active August 9, 2024 13:52
Show Gist options
  • Save markthiessen/3883242 to your computer and use it in GitHub Desktop.
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);
});
});
@pereira-a
Copy link

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
Copy link

suryavi commented Jul 19, 2022

getWeekOfMonth
Screenshot (219)

@dllsystem
Copy link

dllsystem commented Jan 24, 2024

/**

  • 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