javascriptangulardatemomentjsangular-moment

get all day between 2 timestamp


i am trying to get all day between 2 timestamp and for specific day name.

i have a start1 is moment(first date) and end1 is moment(last date). And i have a list of day with id (day).

this.datesDailySelected = [];
var start1 = moment(new Date(this._data.row.plannedDispatch));
var end1 = moment(this.datesForm.controls["dailyExpiryDate"].value);
this.selectedItemsList.forEach((item) => {
  var current = start1.clone();
  var day;
  switch (item.name) {
    case "Sunday":
      day = 0;
      break;
    case "Monday":
      day = 1;
      break;
    case "Tuesday":
      day = 2;
      break;
    case "Wednesday":
      day = 3;
      break;
    case "Thursday":
      day = 4;
      break;
    case "Friday":
      day = 5;
      break;
    case "Saturday":
      day = 6;
      break;
  }
  while (current.day(7 + day).isBefore(end1)) {
    this.datesDailySelected.push(current.clone().format("YYYY-MM-DD"));
  }
  console.log(this.datesDailySelected);
});

wherever i choose 2 date and a specific day name example (friday), i retreive all date without day in this week!

i thing i do something wrong with my code.

Real example:

start1 : "2021-12-20T07:50:00.000Z"
end1: "2021-12-25T07:50:00.000Z" 
day choosed: friday with day = 5

output = empty list.

output must be ["2021-12-24"]

Solution

  • The sample timestamps are UTC, but the working is with local dates so the following does the same. This may produce different results on hosts with different timezone offsets. If you want all UTC, then just change all the methods to UTC methods (setHours to setUTCHours, getDate to getUTCDate, etc.).

    You can convert the day name to number much more simply using an array and indexOf rather than a long switch block.

    Getting the first instance of a particular day is fairly straight forward too, though you have to check that it's not before the start (e.g. if the date range is Thu to Mon and you want Sun, then then the algorithm finds the Sun before Thu, not after). So there's a check and if it's before start, a week is added.

    Then it's just a matter of checking against the end date and pushing a timestamp into the result array for each day, then adding 7 days, etc.

    You can do it all using a library, but it's not that hard in plain JS:

    function getDaysBetween(d1, d2, day) {
      // Convert day name to number
      let days = ['su','mo','tu','we','th','fr','sa'];
      let dayNum = days.indexOf(day.toLowerCase().substr(0,2));
      // Convert timestamps to Dates and set to start of day
      let start = new Date(d1);
      start.setHours(0,0,0,0);
      let end = new Date(d2);
      end.setHours(0,0,0,0);
      // Get first instance of day name in same week as start
      let d = new Date(start);
      d.setDate(d.getDate() - d.getDay() + dayNum);
      // If before start, add 7 days
      if (d < start) d.setDate(d.getDate() + 7);
      
      let result = [];
      while (d <= end) {
        result.push(d.toLocaleDateString('en-CA'));
        d.setDate(d.getDate() + 7)
      }
      
      return result;
    }
    
    
    let start = '2021-12-20T07:50:00.000Z';
    let end = '2021-12-25T07:50:00.000Z'; 
    let day = 'Friday';
    
    console.log(getDaysBetween(start, end, day));