0

I have this arrays

const datesToBeChecked = ['2020-07-03','2020-07-06', '2020-07-13', '2020-07-20']
const dateToCheckFor = '2020-07-12';

I need to get the first nearest date in the past - so when the date is 2020-07-12 i need to get 2020-07-06 from datesToBeChecked.

WHAT I TRIED

I tried this code

datesToBeChecked.forEach(date => {
      let diff = moment(dateToCheckFor).diff(moment(date), 'days');
      console.log(diff);
      if (diff > 0) {
        if (nearestDate) {
          if (moment(date).diff(moment(nearestDate), 'days') < 0) {
            nearestDate = date;
          }
        } else {
          nearestDate = date;
        }
      }
    });

but that gives me the earliest date in the array - 2020-07-03. But i need the first BEFORE THE DATE I CHECK FOR

Petar
  • 119
  • 1
  • 8

5 Answers5

2

Actually your logic is almost there. You don't need the nested if conditional. In essense, what you want is to cache the difference, and compare the current difference with the cached difference. If the cached difference is smaller, then we know the current date is the nearest one. Otherwise, we continue for the search.

This solution will work even if the dates are not sorted in chronological order (oldest to newest):

const datesToBeChecked = ['2020-07-03', '2020-07-06', '2020-07-13', '2020-07-20']
const dateToCheckFor = '2020-07-12';

let nearestDate;
let cachedDiff = Infinity;
datesToBeChecked.forEach(date => {
  let diff = moment(dateToCheckFor).diff(moment(date), 'days');
  if (diff > 0 && diff < cachedDiff) {
    cachedDiff = diff;
    nearestDate = date;
  }
});

console.log(nearestDate);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
Terry
  • 63,248
  • 15
  • 96
  • 118
1

The first element is the closest date in the past (at least yesterday, today results won't show up).

If empty then dateToCheckFor elements does not contain any date in past.

const mappedDates = dateToCheckFor
    .map(d => moment(dateToCheckFor).diff(moment(d), 'days'))
    .filter(diff => diff <= -1)
    .sort()
    .reverse();
omidh
  • 2,526
  • 2
  • 20
  • 37
0

You could try sorting all of the dates in a hash table first. So you would have a hash table:

{
  date1: difference,
  date2: difference,
  ...
}

then you would sort the objects values, such as here: Sorting object property by values

then take the first date from that, which is before the dateToCheckFor

I hope this is not too inefficient for you.

Nils Schwebel
  • 641
  • 4
  • 14
0

Here's one way with good ole vanilla js. Moment.js weighs 230+kb

const datesToBeChecked = ['2020-07-03', '2020-07-06', '2020-07-13', '2020-07-20']
const dateToCheckFor = '2020-07-12';
dateToCheckFor_d = new Date(dateToCheckFor).getTime();
let possibilities = datesToBeChecked.filter(dt => {
  return (new Date(dt).getTime() < dateToCheckFor_d)

})
possibilities.sort().reverse()
console.log(possibilities[0])
Kinglish
  • 23,358
  • 3
  • 22
  • 43
0

In your code just update the below line

if (moment(date).diff(moment(nearestDate), 'days') < 0

to

if (moment(date).diff(moment(nearestDate), 'days') > 0
Slava Rozhnev
  • 9,510
  • 6
  • 23
  • 39