-
-
Save markthiessen/3883242 to your computer and use it in GitHub Desktop.
//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); | |
}); | |
}); |
Thank you very useful.
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}
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}
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
}
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); }`
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);
}
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
}
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}
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;
}
/**
- 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))
Very helpful.