0

I have a function that gets all days of any input dates's week. I use this later on to render a calendar.

However, the dates go from Sunday-Saturday when I want them going from Monday-Sunday. I feel like the would be an easy change but I can't seem to figure it out.

const createNewWeek = (startDate) => {
  const newDates = Array.from(Array(7).keys()).map((idx) => {
    const d = new Date(startDate);
    d.setDate(d.getDate() - d.getDay() + idx);
    return d;
  })
  return newDates
}
console.log(createNewWeek(new Date()))
mplungjan
  • 169,008
  • 28
  • 173
  • 236
Ethan Crabb
  • 302
  • 5
  • 14

2 Answers2

0

Find previous or next monday for a given Date and create an array with 7 subsequent dates starting with the found monday.

Fork this stackblitz project to play with a modified version of this code.

const mondays = {
  next: d => d.getDay === 1 ? 
    d : new Date(+d + 
    ( Math.abs( d.getDay() - (d.getDay() === 0 ? 1 : 8) ) * 864e5 ) ),
  previous: d => d.getDay === 1 ? d : new Date(+d - (d.getDay()-1) * 864e5),
};
const toUtc = d => new Date(d.toUTCString());
const getMonday = (d, next) => next ? mondays.next(d) : mondays.previous(d);
const createWeek = (maybeMonday, next) => 
  [toUtc(getMonday(maybeMonday, next)),0,0,0,0,0,0]
    .map( (_, i, s) => new Date((i * 864e5) + +s[0]) );

// demo
const locale = `en-GB`;
const tls = dates => 
  dates.map((d, i) => d.toLocaleDateString(locale)).join(`\n`);
const now = new Date();
const then = new Date(1927,2,15);

console.log(`Current week for ${
  now.toLocaleDateString(locale)} (today)\n${tls(createWeek(now))}`);
console.log(`Current week for ${
  then.toLocaleDateString(locale)}\n${tls(createWeek(then))}`);
console.log(`Week ahead for ${
  now.toLocaleDateString(locale)} (today)\n${
    tls(createWeek(now, true))}`);
console.log(`Week ahead for ${
  then.toLocaleDateString(locale)}\n${tls(createWeek(then, true))}`);
  
/*
  notes:
  - 864e5 is the number of milliseconds of one day
  - uses utc date to prevent time zone surprises
*/
.as-console-wrapper {
  max-height: 100% !important;
}
KooiInc
  • 119,216
  • 31
  • 141
  • 177
0

As Kooilnc says, get the previous Monday and build an array of 7 dates. The following is an example using basic JS that is likely much more efficient than generating lots of unnecessary arrays purely for the sake of avoiding a boring old for loop.

function getMonToSun(date = new Date()) {
  // Result array
  let week = [];
  // Prior Monday
  let mon = new Date(date.getFullYear(), date.getMonth(),
                     date.getDate() - (date.getDay() || 7) + 1);
  // Build array of 7 dates from Monday
  for (let i=0; i<7; i++) {
    week.push(new Date(mon.getFullYear(), mon.getMonth(), mon.getDate() + i));
  }
  return week;
}

// Current week
console.log(getMonToSun().join('\n'));
// Week of 1 Jan 2000
console.log(getMonToSun(new Date(2000,0,1)).join('\n'));
RobG
  • 142,382
  • 31
  • 172
  • 209
  • *For the record*: the snippet in my answer creates 1 (one) array and uses vanilla (basic) js. – KooiInc Sep 02 '22 at 08:39
  • @KooiInc— It seems to me that `[...Array(6)]` creates two arrays, one of length 6 that is spread to create another array with 7 undefined elements. `[ ...acc, ...]` within *reduce* creates a new array on each iteration, so 7 more arrays, plus one more as the initial value passed to *reduce*. – RobG Sep 02 '22 at 09:02
  • Sure, but I suppose (in *this* case) it's not that much of a performance hit and the browser is highly optimized ([see](https://leanylabs.com/blog/js-forEach-map-reduce-vs-for-for_of/)). – KooiInc Sep 03 '22 at 07:28
  • FYI: the [stackblitz snippet](https://stackblitz.com/edit/js-nwn5kj?file=index.js) now uses a simple `map` – KooiInc Sep 03 '22 at 08:29