Iterate through a range of dates in NodeJS

node.jsDateDatetime

node.js Problem Overview


I would like to iterate through a range of calender dates, each iteration is +1 day. I would use something built around JodaTime in Java - is there something similar in NodeJS?

node.js Solutions


Solution 1 - node.js

You can use moment.js in a node.js application.

npm install moment

Then you can very easily do this:

var moment = require('moment');

var a = moment('2013-01-01');
var b = moment('2013-06-01');

// If you want an exclusive end date (half-open interval)
for (var m = moment(a); m.isBefore(b); m.add(1, 'days')) {
  console.log(m.format('YYYY-MM-DD'));
}

// If you want an inclusive end date (fully-closed interval)
for (var m = moment(a); m.diff(b, 'days') <= 0; m.add(1, 'days')) {
  console.log(m.format('YYYY-MM-DD'));
}

Hmmm... this looks a lot like the code you already wrote in your own answer. Moment.js is a more popular library has tons of features, but I wonder which one performs better? Perhaps you can test and let us know. :)

But neither of these do as much as JodaTime. For that, you need a library that implements the TZDB in JavaScript. I list some of those here.

Also, watch out for problems with JavaScript dates in general. This affects NodeJS as well.

Solution 2 - node.js

I would propose a change to the earlier response by Matt. His code will cause a mutation on the a object. try this...

var moment = require('moment');
var a = moment('2013-01-01');
var b = moment('2013-06-01');
   
for (var m = moment(a); m.isBefore(b); m.add(1, 'days')) {
    console.log(m.format('YYYY-MM-DD'));
}

Solution 3 - node.js

Here's one solution without external libraries:

  var start = new Date('October 1, 2020 03:00:00Z');
  var now = new Date();

  for (var d = start; d < now; d.setDate(d.getDate() + 1)) {
    console.log(d);
  }

Result:

2020-10-01T03:00:00.000Z
2020-10-02T03:00:00.000Z
2020-10-03T03:00:00.000Z
2020-10-04T03:00:00.000Z
2020-10-05T03:00:00.000Z
2020-10-06T03:00:00.000Z

The Z at the end of the first date is for UTC. If you want your time zone, just remove the Z.

Solution 4 - node.js

Use the https://github.com/JerrySievert/node-date-utils framework, then you can iterate easily like this:

require('date-utils');

var d = new Date('2013-01-01');
var e = new Date('2013-06-01');

for(var i = d; i.isBefore(e); i.addDays(1)) {
  console.log(i.toFormat("YYYY-MM-DD"));  
}

Solution 5 - node.js

Another way using momentjs with lodash range:

let start = moment('2021-01-01');
let end = moment('2021-01-10');
_.range(b.diff(a, "d")).forEach((d) =>
  console.log(moment(a).add(d, "d").format("YYYY/MM/DD"))
);

If you don't want to use lodash, you can get a range like shown here

[...Array(b.diff(a, "d")).keys()].forEach((d) =>
  console.log(moment(a).add(d, "d").format("YYYY/MM/DD"))
);

Solution 6 - node.js

Alternative way using moment and while loop.
If you want an exclusive end date

let startDate = moment()
let endDate = moment().add(5, 'days')
while (endDate.isAfter(startDate)) {
    console.log(startDate.format('YYYY-MM-DD'))
    //increment by one day
   startDate = startDate.add(1, 'day')
}

If you want an inclusive end date

let startDate = moment()
let endDate = moment().add(5, 'days')
while (endDate.isSameOrAfter(startDate)) {
    console.log(startDate.format('YYYY-MM-DD'))
    //increment by one day
    startDate = startDate.add(1, 'day')
}

Solution 7 - node.js

As much as there are many utilities for this, they might be cumbersome to integrate into a useful loop to check against data.

This should do the trick. It might be overkill, but you could very easily make this more argument based.

var moment = require('moment');
var _ = require('lodash');

function(collectionsWithDateValues){
  var slots = [];
  var hours = {
    start: 7,   // 7am
    end: 21,    // 9pm
    window: 2   // How long each item should be slotted for.
  };
  var rightNow  = moment().add(0, 'days').hours(hours.start).minute(0).second(0);
  var cutoff    = moment(rightNow).add(14,'days'); // Check the next 2 weeks.
  for( rightNow ; rightNow.isBefore(cutoff) ; rightNow.add(hours.window, 'hours') ){
    // Check if we're going beyond the daily cutoff, go to the next day
    if(rightNow.isAfter(moment(rightNow).hour(hours.end))){
      rightNow.add(1, 'days').hour(hours.start);
    }
    var foundClash = false;
    _.forEach(collectionsWithDateValues,  function(item){
      // Check if the item is within now and the slotted time 
      foundClash = moment(item.date).isBetween(rightNow, moment(rightNow).add(hours.window, 'hours').subtract(1, 'minutes').seconds(59));
    });
  
    if(!foundClash){
      slots.push(rightNow.toString());
    }
  }
  return slots;
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionnwalthamView Question on Stackoverflow
Solution 1 - node.jsMatt Johnson-PintView Answer on Stackoverflow
Solution 2 - node.jsice.nicerView Answer on Stackoverflow
Solution 3 - node.jsmiguelmorinView Answer on Stackoverflow
Solution 4 - node.jsnwalthamView Answer on Stackoverflow
Solution 5 - node.jsManokaran KView Answer on Stackoverflow
Solution 6 - node.jsRijan AdhikariView Answer on Stackoverflow
Solution 7 - node.jsMichael MinorView Answer on Stackoverflow