0

We consider that I have the following dates:

from: 21/09/2019

to: 29/09/2019

The result I would like to have is such a thing:

[
  {
    "day": 21,
    "month": 9,
    "year": 2019
  },
  ...
  {
    "day": 29,
    "month": 9,
    "year": 2019
  }
]

If I had such a thing:

from: 21/09/2019

to: 7/10/2019

The result I would like to have is such a thing:

[
  {
    "day": 21,
    "month": 9,
    "year": 2019
  },
  ...
  {
    "day": 30,
    "month": 9,
    "year": 2019
  },
  ...
  {
    "day": 1,
    "month": 10,
    "year": 2019
  }
  {
    "day": 7,
    "month": 10,
    "year": 2019
  }
]

What I would like to do is print in an array, all the days between the start date and the end date.

I was trying something like this, but I'm having some problems:

let from = "23/09/2019";
let to = "7/10/2019";

function getDaysInMonth(month, year) {
  return new Date(year, month, 0).getDate();
}

function calculate(from, to) {
  let splitF = from.split("/");
  let splitT = to.split("/");
  let array = [];

  let dF = parseInt(splitF[0]);
  let dT = parseInt(splitT[0]);
  let mF = parseInt(splitF[1]);
  let mT = parseInt(splitT[1]);
  let yF = parseInt(splitF[2]);
  let yT = parseInt(splitT[2]);

  let day, init, final;

  while (true) {
    if (mF === mT && yF === yT) {
      day = dT - dF;
    } else {
      day = getDaysInMonth(mF, yF)-dF;
    }
    init = dF;
    final = init + day;
    Array.apply(null, { length: final + 1 })
      .map(Number.call, Number)
      .slice(init)
      .reduce((prev, curr) => {
        let obj = {
          day: curr,
          month: mF,
          year: yF
        };
        array.push(obj);
        return prev;
      }, []);
    if (mF === mT && yF === yT) break;
    mF++;
    dF = 1;
    if (mF === 13) {
      mF = 1;
      yF++;
    }
  }
  return array;
}

console.log(calculate(from, to));
Paul
  • 3,644
  • 9
  • 47
  • 113
  • did you see [this](https://stackoverflow.com/questions/4413590/javascript-get-array-of-dates-between-2-dates)? When you say problems, can you describe the problems you are having? – Paul Rooney Sep 29 '19 at 22:23
  • This is 3 questions in one (parse, add 1 day, format), which have all been answered many, many times before. – RobG Sep 30 '19 at 00:50

3 Answers3

0

One approach would be to extract the numeical "parts" of your input date strings from and to by spliting against / characters:

// Obtain day, month, year integers of the "from" date string
const [fromDay, fromMonth, fromYear] = from.split("/").map(part => Number.parseInt(part));

Once you have these date parts as integers, the date range can be iterated through a for-loop where, per iteration, you add an item object to the result array based on the current iteration of that loop:

// Add an item object with date number for current iteration
result.push({ day, month, year });

Per iteration, you'd also check to see if the next date be iterated is equal to the number "parts" of the to date (as well as incrementing the current month and year as needed):

const numDaysInMonth = (month, year) => new Date(year, month, 0).getDate()
const extractParts = (date) => date.split("/").map(part => Number.parseInt(part));

const calcDaysBetweenDates = (from, to) => {

  const [fromDay, fromMonth, fromYear] = extractParts(from);
  const [toDay, toMonth, toYear] = extractParts(to);
  const result = [];

  // Iterate over from-to range starting at from year/month/day
  for (let year = fromYear, month = fromMonth, day = fromDay;;) {

    // Add item object for current day/month/year to result array
    result.push({
      day,
      month,
      year
    });

    // Increment day
    day++;

    // If next day past current month, reset day, increment month
    if (day > numDaysInMonth(month, year)) {
      month++;
      day = 1;
    }

    // If next month past current year, reset month, increment year
    if (month > 12) {
      month = 1;
      year++;
    }

    // If next day and month and year past to day/month/year, exit loop
    if (day >= toDay && month >= toMonth && year >= toYear) {
      break;
    }
  }

  // Add to date for range inclusivity 
  result.push({
    day: toDay,
    month: toMonth,
    year: toYear
  });

  return result;
}

console.log(calcDaysBetweenDates("21/09/2019", "29/09/2019"));
console.log(calcDaysBetweenDates("21/09/2019", "7/10/2019"));
console.log(calcDaysBetweenDates("25/12/2019", "5/1/2020"));
Dacre Denny
  • 29,664
  • 5
  • 45
  • 65
  • There seems to be a problem with your script, with the second date: "09/21/2019", "7/10/2019" It also gives me 09/31/2019, but this date does not exist. – Paul Sep 29 '19 at 22:32
  • @Paul sorry about that, was calculating the number of days for the next month rather than the current. Just updated script - does that help? – Dacre Denny Sep 30 '19 at 03:19
0

You can add date by 1 to start date and Date object will take care of validating the new date ie next month or next year and all, repeat till end date toDate is greater than start date fromDate.

let from = "23/09/2019";
let to = "29/10/2019";

// convert to date object by interchanging date/month expected by Date function
let fromDate = new Date(from.replace(/([0-9]+)\/([0-9]+)/,'$2/$1'));
let toDate = new Date(to.replace(/([0-9]+)\/([0-9]+)/,'$2/$1'));

let response = [];
while(toDate > fromDate){
  response.push({day: fromDate.getDate(), month: fromDate.getMonth()+1, year: fromDate.getFullYear()});
  fromDate.setDate(fromDate.getDate()+1) // increment date by 1
}

console.log(response)
joyBlanks
  • 6,419
  • 1
  • 22
  • 47
-1

You could use moment together with moment range.

window['moment-range'].extendMoment(moment);

const start = moment('21/09/2019', 'DD/MM/YYYY');
const end = moment('29/09/2019', 'DD/MM/YYYY');

const range = moment.range(start, end);

for (let pt of range.by('day')) {
 console.log(pt.format('DD/MM/YYYY'))
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment-with-locales.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-range/4.0.2/moment-range.js"></script>
baao
  • 71,625
  • 17
  • 143
  • 203