7

I'm trying to make a function to get all the days of the week given the current day. I had a function that i thought was working until i noticed that if the day of the week is near the end of the month, like for example February, i get weird data. Anyone know whats going on and how to fix it?

Console

function days(current) {
  var week = new Array();
  // Starting Monday not Sunday 
  var first = ((current.getDate() - current.getDay()) + 1);
  for (var i = 0; i < 7; i++) {
    week.push(
      new Date(current.setDate(first++))
    );
  }
  return week;
}

var input = new Date(2017, 1, 27);
console.log('input: %s', input);

var result = days(input);
console.log(result.map(d => d.toString()));
.as-console-wrapper{min-height:100%}
mikemaccana
  • 110,530
  • 99
  • 389
  • 494
AJ_
  • 3,787
  • 10
  • 47
  • 82

5 Answers5

13

If you don't want to use some kind of other library like Moment.js you can also change your function a little and then it will work. Try this:

function dates(current) {
    var week= new Array(); 
    // Starting Monday not Sunday
    current.setDate((current.getDate() - current.getDay() +1));
    for (var i = 0; i < 7; i++) {
        week.push(
            new Date(current)
        ); 
        current.setDate(current.getDate() +1);
    }
    return week; 
}
console.log(dates(new Date(2017, 1, 27)));
Joe Pi
  • 372
  • 3
  • 13
  • Any idea why this becomes this new Date("2017-02-27"); Becomes this Sun Feb 26 2017 18:00:00 GMT-0600 (Central Standard Time) – AJ_ Mar 24 '17 at 21:16
  • 1
    @John This is because of your timezone (GMT-6). The Date inserted into new Date() needs to be in GMT and if no time is set 0:00h will be used. Because of your time zone which is GMT-6 your result will be 6 hours less when printed out in your browser because it will be converted into your timezone. – Joe Pi Mar 24 '17 at 21:27
  • So how do i detect the correct time, and/or convert the string to the correct date object ? I get my dates via strings like the one above – AJ_ Mar 24 '17 at 21:35
  • The answer should be in the answer, not a following comment. It's also not correct, it has nothing to do with timezone, everything is treated as local. See jakeehoffmann's answer. – RobG Mar 24 '17 at 22:46
  • @John—both this answer and jakeehoffmann's have a fix. Jake's also explains why you had the issue. – RobG Mar 28 '17 at 00:35
6

You can use Moment.js library - utility library for dates/time operations

Here's examplary code to get current week's dates starting from monday:

function getThisWeekDates() {
  var weekDates= []; 

  for (var i = 1; i <= 7; i++) {
    weekDates.push(moment().day(i)); 
  }

  return weekDates; 
}

var thisWeekDates = getThisWeekDates();

thisWeekDates.forEach(function(date){ console.log(date.format());});
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.js"></script>

The code above prints following results to the console:

2017-03-20T21:26:27+01:00
2017-03-21T21:26:27+01:00
2017-03-22T21:26:27+01:00
2017-03-23T21:26:27+01:00
2017-03-24T21:26:27+01:00
2017-03-25T21:26:27+01:00
2017-03-26T21:26:27+02:00
Ivaylo Slavov
  • 8,839
  • 12
  • 65
  • 108
Andrew B
  • 860
  • 1
  • 14
  • 23
3

I will trace your code using your example of Feb 27, 2017:

first = 27 - 1 + 1 = 27

loop:

Feb.setDate(27) = 27 feb
Feb.setDate(28) = 28 feb
Feb.setDate(29) = Not 29 days in Feb. So it sets current to 29-28 = 1st day of March
March.setDate(30) = March 30
March.setDate(31) = March 31     
March.setDate(32) = Not 32 days in March. So it sets current to 31-32 = 1st of April..
April.setDate(33) = Not 33 days in April. So it sets current day 33-30 = 3rd day of May. 

Please note that I used the shorthand of Month.setDate() to show the month of the current Date object when it was being called.

So the issue is with your understanding of setDate that is being used on current. It changes the month and if the value you use isn't a day in the month it adjusts the month and day appropriately. I hope this cleared things up for you.

For how to add one to a date, see Add +1 to current date. Adapted to your code, you can set current to the first day of the week then just keep adding 1 day and pushing copies to the array:

function days(current) {
  var week = [];
  // Starting Monday not Sunday 
  var first = current.getDate() - current.getDay() + 1;
  current.setDate(first);
  for (var i = 0; i < 7; i++) {
    week.push(new Date(+current));
    current.setDate(current.getDate()+1);
  }
  return week;
}

var input = new Date(2017, 1, 27);
console.log('input: %s', input);

var result = days(input);
console.log(result.map(d => d.toString()));

Note that this changes the date passed in (per the original code), you may want to make current a copy to avoid that.

Community
  • 1
  • 1
jakeehoffmann
  • 1,364
  • 14
  • 22
  • This is a good explanation of why the code isn't working, but OP asked how to fix it. – Jordan Running Mar 24 '17 at 21:12
  • @Jordan Well, he asked if anyone knew what was going on AND how to fix it. I suppose I only partially answered then. Just trying to help :) – jakeehoffmann Mar 24 '17 at 21:55
  • @jakeehoffmann, i appreciated your explanation and your additional content. I wish i could mark two answers. – AJ_ Mar 27 '17 at 14:50
2

Suppose monday starts the week, you can calculate monday and go to sunday. getDategives you the day of the week, and Sunday starts at 0. With momnday, we get just offset forward to 6 days to get sunday

mondayThisWeek(date: Date): Date {
  const d = new Date(date)
  const day = d.getDay()
  const diff = d.getDate() - day + (day === 0 ? -6 : 1)
  return new Date(d.setDate(diff))
}

const offsetDate = (base: Date, count: number): Date => {
  const date = new Date(base)
  date.setDate(base.getDate() + count)
  return date
}

thisWeek(today: Date): TimeRange {
  const monday = mondayThisWeek(today)
  return {
    startDate: monday,
    endDate: offsetDate(monday, 6)
  }
}
onmyway133
  • 45,645
  • 31
  • 257
  • 263
0

This can be achieved easly using moment

const getWeekDates = () => {

  let weekDates = [];

  for (let i = 0; i < 7; i++)
    weekDates.push(moment().add(i, 'd'));

  return weekDates;
};


console.log(getWeekDates());
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.js"></script>
Goor Lavi
  • 412
  • 3
  • 16