DEV Community

loading...
Cover image for Using Moment's isBetween()

Using Moment's isBetween()

Doaa Mahely
Software engineer and web developer. I like to code.
・4 min read

This post uses Moment.js version 2.29.1. Moment.js is currently considered to be in maintenance mode and isn't encouraged to be used in new projects. More here.

This week I was working on a cron job that pulls data from an external API to check if any values were added in the last 10 minutes. The API didn't allow filtering by time, so I had to pull all the data that was added that day, then go over them and check if any values were added in the last 10 minutes.

Working with dates and time is always tricky, and this was no exception. For this feature, I opted to use Moment.js over native JavaScript because it's easier to read and it was already a dependency. Let's say we want to appreciate anyone who takes the time to comment on our posts. The example I'll use will get all comments made today, then filter them out to return the comments made in the last 10 minutes so we can like them or reply to them with an emoji πŸ¦„.

We'll start with creating the function and defining the format that the comments' dates and times are returned in from the API.

const getLatestComments = (todayComments) => {

  const dateTimeFormat = "M/DD/YYYY hh:mm:ss A";
};
Enter fullscreen mode Exit fullscreen mode

We will need two other variables, the start time and end time we'll be filtering between. The start time will be the current date and time minus 10 minutes, and the end time will just be the current date and time.

const getLatestComments = (todayComments) => {

  const dateTimeFormat = "M/DD/YYYY hh:mm:ss A";

  const start = moment().subtract(10, "minutes").format(); // now minus 10 minutes
  const end = moment().format(); // now
};
Enter fullscreen mode Exit fullscreen mode

We can use moment() only to get the current date and time, but with calling format() on it, we can get a neatly formatted string back instead of the entire moment object.

Using moment() will return an object while using moment().format() will return a string

Next, let's see how we can check if the comment's date and time is between our two variables. Moment.js has this handy function named isBetween() that returns a boolean. This method takes two moment-like objects as parameters, where a moment-like object can be a moment object, string, number, date or array. In our case, we'll be using the strings we created above. It's worth noting that this function is exclusive by default, but accepts an additional parameter to specify inclusivity.

The next natural step for me was to do something like this, where I first create a moment object of each comment's publishing date and time, then format it as I did with the previous variables:

const getLatestComments = (todayComments) => {

  const dateTimeFormat = "M/DD/YYYY hh:mm:ss A";

  const start = moment().subtract(10, "minutes").format(); // now minus 10 minutes
  const end = moment().format(); // now

  const latestComments = todayComments.filter((comment) => 
    moment(comment.dateTime).format().isBetween(start, end)
  );
};
Enter fullscreen mode Exit fullscreen mode

But here, we'll start to notice two things in the console:

// console

"Deprecation warning: value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are discouraged. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.

TypeError: moment(comment.dateTime).format().isBetween is not a function. (In 'moment(comment.time).format().isBetween(start, end)', 'moment(comment.dateTime).format().isBetween' is undefined)
Enter fullscreen mode Exit fullscreen mode

This is because Moment.js doesn't know what format the date and time we're passing it is in, so it's not able to reformat it. We can easily fix this by passing the format the comment's date and time will be in.

moment(comment.dateTime, dateTimeFormat).isBetween(start, end);
Enter fullscreen mode Exit fullscreen mode

Notice how I removed the subsequent format(), and that's because the format() function returns a string, while moment() returns an object, and we need an object so we can call the isBetween() function on it. So this is what our complete function will look like:

const getLatestComments = (todayComments) => {

  const dateTimeFormat = "M/DD/YYYY hh:mm:ss A";

  const start = moment().subtract(10, "minutes").format(); // now minus 10 minutes
  const end = moment().format(); // now

  const latestComments = todayComments.filter((comment) => 
    moment(comment.dateTime, dateTimeFormat).isBetween(start, end)
  );

  return latestComments;
};
Enter fullscreen mode Exit fullscreen mode

Assuming that today is the 16th of October, 2020 and the current time is 12:10 PM, let's see our function in action.

// example input
const comments = [
  {
    comment: 'I would love to do something similar in my website.',
    username: 'Barbara',
    dateTime: '10/16/2020 12:04:13 PM'
  },
  {
    comment: 'Great job!',
    username: 'Jane',
    dateTime: '10/16/2020 12:01:07 PM'
  },
  {
    comment: 'Keep up the good work 😊',
    username: 'Jess',
    dateTime: '10/16/2020 11:57:55 AM'
  }
 ...
];

const latestComments = getLatestComments(comments);
console.log(latestComments);
// output 
[
  {
    comment: 'I would love to do something similar in my website.',
    username: 'Barbara',
    dateTime: '10/16/2020 12:04:13 PM'
  },
  {
    comment: 'Great job!',
    username: 'Jane',
    dateTime: '10/16/2020 12:01:07 PM'
  }
]
Enter fullscreen mode Exit fullscreen mode

Thanks for reading! Until next time πŸ‘‹

Cover photo by Heather Zabriskie on Unsplash.

Discussion (0)