0

I have an array of dates that are Sundays two weeks apart:

var payPeriodArray = ['08/04/2019',
'08/18/2019',
'09/01/2019',
'09/15/2019',
'09/29/2019',
'10/13/2019',
'10/27/2019',
'11/10/2019',
'11/24/2019',
'12/08/2019',
'12/24/2019'
]

If I wanted to pull the next Sunday after today (9/3/2019) and set it as proposed_start_date, how would I do that with Javascript?

var proposed_start_date;

for(var i=0; i<payPeriodArray.length; i++){
        if(payPeriodArray[i].ppStart > today){
            proposed_start_date = ?
        }
    }
Dave
  • 1,257
  • 2
  • 27
  • 58
  • 2
    Do your requirements force you to use the array, or could you just calculate the next Sunday without predefining the dates? – IronFlare Sep 03 '19 at 19:51
  • I agree with IronFlare. I'd use a date library for all of this instead of string dates. Is there a reason you're doing this by hand and stuck with an array? – ggorlen Sep 03 '19 at 19:51

4 Answers4

1

@RobG has made a good point that using new Date(d) is not recommended. See this question for why. I have changed the code to use a parseDate function.


You can use the Date object to compare dates.

    // parse a date in mm/dd/yyyy format
    function parseDate(input) {
      var parts = input.split('/');
      // new Date(year, month [, day [, hours[, minutes[, seconds[, ms]]]]])
      return new Date(parts[2], parts[0]-1, parts[1]); // Note: months are 0-based
    }

    var payPeriodArray = [
        '08/04/2019',
        '08/18/2019',
        '09/01/2019',
        '09/15/2019',
        '09/29/2019',
        '10/13/2019',
        '10/27/2019',
        '11/10/2019',
        '11/24/2019',
        '12/08/2019',
        '12/24/2019'
    ];

    var proposed_start_date, today = new Date();

    for(var i=0; i<payPeriodArray.length; i++){
        if(parseDate(payPeriodArray[i]) > today){
            proposed_start_date = payPeriodArray[i]
            break;
        }
    }
    
    console.log(proposed_start_date);

Note the break I added, its important to stop the loop once the next pay period is found or else you will always get the last date in the array.

You could also simplify the loop down using find

    // parse a date in mm/dd/yyyy format
    function parseDate(input) {
      var parts = input.split('/');
      // new Date(year, month [, day [, hours[, minutes[, seconds[, ms]]]]])
      return new Date(parts[2], parts[0]-1, parts[1]); // Note: months are 0-based
    }

    var payPeriodArray = [
        '08/04/2019',
        '08/18/2019',
        '09/01/2019',
        '09/15/2019',
        '09/29/2019',
        '10/13/2019',
        '10/27/2019',
        '11/10/2019',
        '11/24/2019',
        '12/08/2019',
        '12/24/2019'
    ];

    var proposed_start_date = payPeriodArray.find(d => parseDate(d) > new Date());
    
    console.log(proposed_start_date);
ug_
  • 11,267
  • 2
  • 35
  • 52
  • 1
    Though `new Date(d)` is [not recommended](http://stackoverflow.com/questions/2587345/why-does-date-parse-give-incorrect-results). ;-) – RobG Sep 03 '19 at 20:34
0

I would first map the array to have dates instead of strings by using the moment.js library. From there I would have a function that receives a day as a starting point, a weekday and an array to check as demonstrated below:

import * as moment from 'moment';

var payPeriodArray = [...]
const payPeriodDates = payPeriodArray.map( period => moment(period))

//then I would have a function to pull data based on the //after that day


function getDates(afterDayString,weekDay,array){

//weekDay must be an integer being 0- Sunday, 1- Tuesday
// and so on
const afterDate = moment(afterDayString);

    //filtering all dates that are before afterDayString 
//and are the day of the week required
return array.filter(date => afterDate.isBefore(date) &&
date.day() === weekDay)

}
iwaduarte
  • 1,600
  • 17
  • 23
0
var payPeriodArray = ['08/04/2019',
'08/18/2019',
'09/01/2019',
'09/15/2019',
'09/29/2019',
'10/13/2019',
'10/27/2019',
'11/10/2019',
'11/24/2019',
'12/08/2019',
'12/24/2019'
];

var proposed_start_date="";<br>
var today=new Date().getTime();<br>
for(var i=0; i&lt;payPeriodArray.length; i++){<br>
  var d=new Date(payPeriodArray[i]);<br>
  if(d.getTime() &gt; today && d.getDay()==0){<br>
    proposed_start_date = payPeriodArray[i];
}
console.log(proposed_start_date)<br><br>

Here what we are doing is that we are comparing the milliseconds till today.
If the milliseconds till the stored date is greater than milliseconds till today then a check for day is put where getDay() function returns 0 for Sunday, 1 for Monday and so on...
If we get a Sunday after the given date then that day is stored and the loop breaks

If you want also want to compare the dates in order to get the nearest date from the array of dates then instead of break in the if loop you can do the following:

if(proposed_start_date==""){
  proposed_start_date=payPeriodArray[i];
}
else{
  if(new Date(proposed_start_date).getTime()&gt;d.getTime()){
    proposed_start_date=payPeriodArray[i];
  }
}
zendka
  • 1,074
  • 12
  • 11
0

Brute force and assuming no particular order to dates is the obvious solution. Runs in linear time. Something like this:

function findNextDate( now = Date.now() ) {
  let next = undefined;

  for ( const dt of dates ) {
    next = next  === undefined
      ? next
      : dt < next
      ? dt
      : next
      ;
  }

  return next;
}

But if one can assume an ordered collection, use a modified binary search like this:

const dates = [ ... ];

function findNextDate( now = Date.now() ) {
  if ( dates.length === 0 ) return undefined;

  let lo = 0 ;
  let hi = dates.length;

  while ( lo != hi ) {
    let mid = Math.floor( (lo+hi) / 2 );

    if ( dates[mid] > now ) {
      hi = mid;
    } else {
      lo = mid+1;
    }

  }

  const next = dates[lo];
  return next;
}

which will return the smallest item in the ordered array such that it is greater than the target value. Credits to this answer to the question, Find the first element in a sorted array that is greater than the target

A more open-ended solution is a little date arithmetic instead of an array:

function getSundayNext( dtNow = new Date() ) {
  const dow = dtNow.getDay();
  const daysUntilSunday = 7 - dow;

  const nextSunday = new Date( dtNow.valueOf() );
  nextSunday.setDate( dtNow.getDate() + daysUntilSunday );
  nextSunday.setHours(0);
  nextSunday.setMinutes(0);
  nextSunday.setSeconds(0);
  nextSunday.setMilliseconds(0);

  return nextSunday;
}
Nicholas Carey
  • 71,308
  • 16
  • 93
  • 135