2

I have the weekday value (0-6 for Sun-Sat)...how do I get an array of days (starting on Sunday for the given week?

Here is what I'm trying to do:

A user clicks a day (ie: May 10) and it generates an array of the dates for the current week:


    function selectWeek(date) {
        selectedWeek = [];

        let d = new Date(date.key);

        console.log(d);
        console.log(date.weekday, 'weekday');

        console.log(date);
        for (let i = 0; i < date.weekday; i++) {
            console.log(i, 'pre');
            let currD = d.setDate(d.getDate() - i).toString();
            console.log(currD);
            selectedWeek.push(currD);
        }
        for (let i = date.weekday; i < 7; i++) {
            console.log(i, 'post');
            selectedWeek.push(d.setDate(d.getDate() + i).toString());
        }
        console.log(selectedWeek);
    }

I need Sunday through Saturday date objects.

I am not using a date library so prefer vanilla javascript solutions.

chovy
  • 72,281
  • 52
  • 227
  • 295

4 Answers4

3

Create an array with 7 elements, subtract the weekday and add the index as day:

function selectWeek(date) {
  return Array(7).fill(new Date(date)).map((el, idx) =>
    new Date(el.setDate(el.getDate() - el.getDay() + idx)))
}

const date = new Date();
console.log(selectWeek(date));

I'm using

fill(new Date(date))

to create a copy and not modify the argument. You can get the days of a month with the same concept:

function selectMonth(date) {
  return Array(31).fill(new Date(date)).map((el, idx) =>
    new Date(el.setDate(1 + idx))).filter(el => el.getMonth() === date.getMonth());
}

const date = new Date();
console.log(selectMonth(date));
jabaa
  • 5,844
  • 3
  • 9
  • 30
  • why do I need `selectWeek(date)` at the end? – chovy Feb 18 '22 at 20:58
  • I like how compact is this idea. – MMMahdy-PAPION Feb 18 '22 at 21:00
  • @chovy The line `console.log(selectWeek(date));` is for demonstration when you click on "Run code snippet". It shows you the result array. – jabaa Feb 18 '22 at 21:12
  • but why pass the `date` argument? – chovy Feb 18 '22 at 21:24
  • @chovy The function in your question has a parameter. I copied the API. I wanted to demonstrate the result and the function expects an argument. – jabaa Feb 18 '22 at 21:45
  • Oh sorry. I thought you were indexing the gnlobal array – chovy Feb 18 '22 at 22:01
  • Doesn’t this just get the next 7 days? Not exactly what I want – chovy Feb 18 '22 at 22:02
  • @chovy No, it returns the week starting with sunday. – jabaa Feb 18 '22 at 22:02
  • Can you add some comments? It looks like you have an array of datenpassed in and you add 1 to each – chovy Feb 18 '22 at 22:02
  • @chovy You have the description above. `Array(7)` creates an element with 7 elements. `el.setDate(el.getDate() - el.getDay())` calculates the date of sunday. `el.setDate(el.getDate() - el.getDay() + 1)` calculated the date of monday. ... Let's say `el` is wednesday. `el.getDate() - el.getDay()` is the date of the sunday. With `idx` every day of that week is generated. – jabaa Feb 18 '22 at 22:04
  • ahh...so you're resetting each el to sunday and then adding the idx value to it....makes sense. – chovy Feb 18 '22 at 23:32
  • confusing but clever, I accepted this as the answer. – chovy Feb 18 '22 at 23:43
  • 2
    @chovy All 4 answers have the same logic. Get the date, subtract the weekday, add a counter. Some are more verbose, mine is compact, but still readable for most professional JavaScript developers. Chained methods and pipes are very common in JavaScript code. The only logic is this snippet: `el.setDate(el.getDate() - el.getDay() + idx)`. Others use a loop to do this calculation and I use `.map`. – jabaa Feb 18 '22 at 23:49
  • Yeah, I missed the fact that you prefilled the array with current date 7 times, it makes more sense now. But yeah I appreciate chaining like this. – chovy Feb 18 '22 at 23:57
  • so this works great for a week....but does not work for a month (ie: get an array of all days in a given month). I get dates all over the place no idea why – chovy Feb 21 '22 at 19:00
  • @chovy I added a code for the month. – jabaa Feb 21 '22 at 21:21
  • not all months have 31 days....does this account for that? – chovy Feb 22 '22 at 01:08
  • also one bug I see surface with this code is the timezone is not set, so I'm trying to match tasks with a list of days for the month and on 31 or 1 there is some ambiguity....it seems that the date I'm using for the task has tz, but this logic does not. – chovy Feb 22 '22 at 01:09
  • @chovy Yes, it accounts for that. You can click "Run code snippet" and see the result. For February it returns 28 elements. All elements in the array have the same time. A JavaScript `Date` object doesn't contain a timezone. The time zone is added when the `Date` object converted to a string and printed. – jabaa Feb 22 '22 at 11:05
  • @chovy _"n 31 or 1 there is some ambiguity....it seems that the date I'm using for the task has tz, but this logic does not."_ I can't reproduce this problem. Can you provide an example? Are you sending timestamps to a backend? Two different systems can have two different time zones configured. 2022-02-28T23:30:00.0-01 is 2022-03-01T0:30:00.0+00. It's the same date object with the same value on a different system. A date object only contains the number of milliseconds since epoch. Both timestamps are the same value 1646091000000 interpreted by two different servers on different locations. – jabaa Feb 22 '22 at 11:51
1

here's how I would solve this one:

function selectWeek(date) {
        let selectWeek = [];
        for (let i=0; i<7; i++) {
          let weekday = new Date(date) // clone the selected date, so we don't mutate it accidentally.
          let selectedWeekdayIndex = date.getDay() // i.e. 5 for friday
          let selectedDay = date.getDate() // 1-31, depending on the date
          weekday.setDate(selectedDay - selectedWeekdayIndex + i)
          selectWeek = [...selectWeek, weekday]
        }
        return selectWeek;
    }

Let's take today's date as an example: 18.02.22. Friday. We do 6 iterations. On first one we get the selectedWeekdayIndex, which is 5 for friday. We clone the date and re-set it's day (18) reducing it by this number: 18-5 = 13. This is the day for Sunday. Then we go on incrementing days by one to fill the rest of the week.

Of course it can be optimised and written much shorter, but I tried to show and explain the logic.

Gleb Kostyunin
  • 3,743
  • 2
  • 19
  • 36
  • why are you adding weekday at the end? it may be a wednesday – chovy Feb 18 '22 at 20:21
  • Try running it, it returns a proper week starting from sunday. I add a weekday to the end of each iteration. I'll try to write some more description. – Gleb Kostyunin Feb 18 '22 at 20:23
  • yeah it works but I don't understand how. This seems retundant: ` let weekday = new Date(date)` why not set at the beginning? – chovy Feb 18 '22 at 20:24
  • updated answer with more details and broken code into more steps for understanding – Gleb Kostyunin Feb 18 '22 at 20:35
  • gotcha, that makes so whatever current weekday is you just reset the first day to Sunday (doing some math) then you iterate through all days in week. Makes more sense. I was approaching it by going backwards, and then going forwards. – chovy Feb 18 '22 at 20:57
  • Yep, weekday is just a placeholder for the day that we're calculating on each iteration. And we start from sunday. – Gleb Kostyunin Feb 18 '22 at 20:58
0

The .getDay() gives you the day of the week.

function selectWeek(date) {
  const selectWeek = [];
  let temp = date;
  while (temp.getDay() > 0) temp.setDate(temp.getDate() - 1); // find Sunday
  // get the rest of the week in the only do while loop ever created
  do {
    selectWeek.push(new Date(temp));
    temp.setDate(temp.getDate() + 1);
  } while (temp.getDay() !== 0);

  return selectWeek;
  /* for display purposes only */
  // const dates = selectWeek.map((date) => date.toString());
  // console.log(dates);
}

selectWeek(new Date());
selectWeek(new Date("2020-01-01"));
selectWeek(new Date("december 25, 1990"));
JakeAve
  • 279
  • 2
  • 6
0

Did you check Date prototypes before?

I think Date.prototype.getDay() can do what you want:

function selectWeekDays(date) {
  var i,
      d = new Date(date),
      a = [];
  // console.log(d.getDay());   // Number of the day
  d.setDate(d.getDate() - d.getDay() - 1);   // Set date one day before first day of week
  for (i=0; i<7; i++) {
    d.setDate(d.getDate() + 1);   // Add one day
    a.push(d.valueOf());
  }
  return a;
}

var result = selectWeekDays('2022-01-01') // Satureday = 6

console.log(result); 
result.forEach(e => console.log(new Date(e).toString()));
MMMahdy-PAPION
  • 915
  • 10
  • 15