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]
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]
Share
Improve this question
edited Jul 1, 2019 at 19:50
Dalton Cézane
3,7922 gold badges40 silver badges62 bronze badges
asked Jul 1, 2019 at 19:15
DaveDave
1,2773 gold badges29 silver badges64 bronze badges
2
- There are functions to create dates & add to dates, so you can build what you describe out of those. – Scott Hunter 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 remends Luxon for new app development. There's also date-fns, and js-joda to choose from. – Matt Johnson-Pint Commented Jul 1, 2019 at 22:14
5 Answers
Reset to default 3Maybe 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 parison', endTimer.getTime() - startTimer.getTime());
<script src="https://cdnjs.cloudflare./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 parison. 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 parison', endTimer.getTime() - startTimer.getTime());
<script src="https://cdnjs.cloudflare./ajax/libs/moment.js/2.12.0/moment.js"></script>
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;
}
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)) { /* ... */ }
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./docs/#/manipulating/add/
And another project which is built on top of momentjs would be this https://github./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.
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))