1

Our team is just starting to use moment.js for date queries and is wondering if there's a function that can create an array of dates that recur x days apart. For instance if the start date is 7/1/2019 and the end date is 6/30/2020 and the interval is 7 days; is there a moment function that can create an array of dates that looks like this:

[7/8/2019,
7/15/2019,
7/22/2019,
7/29/2019,
8/5/2019,
...
6/29/2020]
2
  • There are functions to create dates & add to dates, so you can build what you describe out of those. Commented Jul 1, 2019 at 19:17
  • With regard to "Our team is just starting to use moment.js...". Please consider learning something else instead. The Moment team recommends Luxon for new app development. There's also date-fns, and js-joda to choose from. Commented Jul 1, 2019 at 22:14

5 Answers 5

3

Maybe not a specific moment function, but certainly moment provides all the ingredients. Look at add() (for adding 7 days) and isBefore() (for the end date).

I've made a snippet that does something close to what you're asking:

var startDate = '1940-07-01';
var endDate = '2020-06-30'

var current = new moment(startDate);
var end = new moment(endDate);

var dates = [];

var startTimer = new Date();
while (current.isBefore(endDate)) {
  dates.push(current.format('MM-DD-YYYY'));
  current.add(7, 'days');
}
var endTimer = new Date();
console.log('Using isBefore took', endTimer.getTime() - startTimer.getTime());



current = new moment(startDate);
dates = [];
startTimer = new Date();
while (current < end) {
  dates.push(current.format('MM-DD-YYYY'));
  current.add(7, 'days');
}
endTimer = new Date();
console.log('Using simple comparison', endTimer.getTime() - startTimer.getTime());
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.12.0/moment.js"></script>

-- EDIT --

This is quite an old answer but it recently got some views so I want to point out something I've learned since getting more familiar with moment.

isBefore carries considerable overhead, and in fact it's much faster to user a simple comparison. That is to say:

current.isBefore(endDate)

is much slower than, (after you make a moment object from endDate)

var end = new moment(endDate);
if (current < endDate);

If you run the next snippet, where I've increased the time range to show the difference, you'll see the second approach is considerably faster:

var startDate = '1940-07-01';
var endDate = '2020-06-30'

var current = new moment(startDate);
var end = new moment(endDate);

var dates = [];

var startTimer = new Date();
while (current.isBefore(endDate)) {
  dates.push(current.format('MM-DD-YYYY'));
  current.add(7, 'days');
}
var endTimer = new Date();
console.log('Using isBefore took', endTimer.getTime() - startTimer.getTime());



current = new moment(startDate);
dates = [];
startTimer = new Date();
while (current < end) {
  dates.push(current.format('MM-DD-YYYY'));
  current.add(7, 'days');
}
endTimer = new Date();
console.log('Using simple comparison', endTimer.getTime() - startTimer.getTime());
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.12.0/moment.js"></script>

Sign up to request clarification or add additional context in comments.

Comments

3

Just create a function which will accept the start and end dates and an interval and keep adding to an array the dates until the to date.

const datesArray = (from, to, interval) => {
  let ret = [];
  const fromDate = moment(from, 'DD-MM-YYYY');
  const toDate = moment(to, 'DD-MM-YYYY');
  let date = fromDate.add(interval, 'days');
  while(toDate > date) {
    ret.push(date.format('MM-DD-YYYY'));
    date = moment(date).add(interval, 'days');
  }
  return ret;
}

Comments

1

You can use for-of loops and make arrays with a generator function.

function* dateRange(start, end, interval) {
  start = moment(start);
  end = moment(end);
  interval = moment.duration(interval);
  while (start.isBefore(end)) {
    yield start;
    start.add(interval);
  }
}

Usage:

const dates = [...dateRange(start, end, interval)];
for (date of dateRange(start, end, interval)) { /* ... */ }

Comments

0

You can use momentJS add function for this. For an example

moment().add(7, 'days');

You can just loop through by adding interval to the starting date. https://momentjs.com/docs/#/manipulating/add/

And another project which is built on top of momentjs would be this https://github.com/rotaready/moment-range where you can directly get ranges with intervals. But if this is the only requirement it's better to go with a simple function.

Comments

0

Create a generator to have a flexible solution:

/**
 * @param start: moment instance not included in result.
 * @param end: moment instance not included in result.
 * @param step: moment duration instance.
 * @return Generator for moment instances between start and end.
 */
function* generateMoments(start, end, step) {
  const variableMoment = start.clone();
  while(true) {
    variableMoment.add(step);
    if(variableMoment < end) {
      yield variableMoment.clone();
    } else {
      break;
    }
  }
}

And ask it for the date list:

Array.from(
  generateMoments(moment('2019-07-01'), moment('2020-06-30'), moment.duration({ days: 7}))
).map(m => m.format(localeDependentFormat))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.