1

I have this function that determines if two sets of dates are overlapping. When the set of dates are in the same year, it works correctly and returns true if there's overlap. If one of the dates is from a previous year, the comparison fails to detect the overlap.

For instance:

var obj = { startDate1: "02/01/2020", 
            endDate1: "03/01/2020", 
            startDate2:"02/05/2020", 
            endDate2:"02/15/2020"  }

Using:

if ((obj.endDate1 >= obj.startDate2 && obj.startDate1 <= obj.endDate2) ||
    (obj.endDate2 >= obj.startDate1 && obj.startDate2 <= obj.endDate1)) {  
         
    }

Returns true since the dates overlap.

However, when startDate1 is in a different year (2019), like so:

var obj = { startDate1: "12/01/2019", 
                endDate1: "03/01/2020", 
                startDate2:"02/05/2020", 
                endDate2:"02/15/2020"  } 

The expression above fails to detect the overlap even though startDate1 and endDate1 do in fact overlap with startDate2 and endDate2.

I've tried using moment and regex to format the dates, but to no avail. Any ideas what I'm doing wrong?

Edit: Here's how I'm using moment:

                        const obj = {
                            startDate1: moment(new Date(value.startDate)).format("MM/DD/YYYY"),
                            endDate1: moment(new Date(value.endDate)).format("MM/DD/YYYY"),
                            startDate2: moment(new Date(startDate)).format("MM/DD/YYYY"),
                            endDate2: moment(new Date(endDate)).format("MM/DD/YYYY")
                        };

The values I'm passing in to new Date are iso date strings.

Sorry for the confusion..

Edit #2/Answer:

I just converted the dates using native JS Date.parse.

const obj = {
             certStart: Date.parse(value.startDate),
             certEnd: Date.parse(value.endDate),
             startDate: Date.parse(startDate),
             endDate: Date.parse(endDate)    };
Crumblenautjs
  • 169
  • 1
  • 3
  • 24

5 Answers5

2
  1. Using the Native Date function in js
var obj = { 
   startDate1: "02/01/2020", 
   endDate1: "03/01/2020", 
   startDate2:"02/05/2020", 
   endDate2:"02/15/2020"
};
// Create a clone of obj object and convert values to timestamp.
var $dates = {};
$dates.startDate1 = new Date(obj.startDate1).getTime();
$dates.startDate2 = new Date(obj.startDate2).getTime();
$dates.endDate1 = new Date(obj.endDate1).getTime();
$dates.endDate2 = new Date(obj.endDate2).getTime();
  1. Comparing time:
if (($dates.endDate1 >= $dates.startDate2 && $dates.startDate1 <= $dates.endDate2) ||
    ($dates.endDate2 >= $dates.startDate1 && $dates.startDate2 <= $dates.endDate1)) {  
         // etc...
}
Rahul Bhobe
  • 4,165
  • 4
  • 17
  • 32
Ali Torki
  • 1,929
  • 16
  • 26
1

Use new Date() or moment.js to create and manipule dates.

var obj = { startDate1: moment("12/01/2019"), 
            endDate1: moment("03/01/2020"), 
            startDate2:moment("02/05/2020"), 
            endDate2:moment("02/15/2020")} 

and moment functions to manipulate dates

JB_DELR
  • 737
  • 1
  • 4
  • 7
  • Does moment correctly and consistently infer that the format is MM/DD/YYYY here? And is it dependent on the browser's locale? Seems like a risky bet to assume that this will work consistently... – Lionel Rowe Sep 11 '20 at 17:27
  • You are right, it's moment("12-25-1995", "MM-DD-YYYY"); to parse. see the doc: https://momentjs.com/docs/#/parsing/ – JB_DELR Sep 11 '20 at 17:32
1

Parse date string to Date, then get its value as a number:

const [m, d, y] = dateStr.split('/').map(Number)

// month is 0-indexed, whereas year and day are 1-indexed
const dateVal = new Date(y, m - 1, d).valueOf()

Then, you can easily compare them with >, <, and so on.

Lionel Rowe
  • 5,164
  • 1
  • 14
  • 27
  • No need for all that, `new Date(dateStr)` will work because the dates are in a recognizable format. – Titus Sep 11 '20 at 17:29
  • `DD/MM/YYYY` is also a recognizable format. It looks like you're right that it works, though, at least in Chrome - seems a little too "magickey" for my taste though. MDN mentions it's "strongly discouraged" in the article for the Date constructor: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date – Lionel Rowe Sep 11 '20 at 17:34
1

Despite your tag, it doesn't seem like you are actually formatting the dates using momentjs - unless you aren't sharing some of the code. It really looks like you are making string comparisons. For date comparison in general, I suggest reading the related: Compare two dates with JavaScript

Relevant MDN on Date: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date

And don't forget to reference the moment.js docs: https://momentjs.com/docs/

EDIT: As already pointed out, you are using .format(), which returns a display string https://momentjs.com/docs/#/displaying/format/ - so you're still comparing strings instead of dates.

You may want to checkout isBetween: https://momentjs.com/docs/#/query/is-between/

1

If the date string is in YYYY/MM/DD format then the string comparison will work.

var obj = {
  startDate1: "2019/12/01",
  endDate1: "2020/03/01",
  startDate2: "2020/02/05",
  endDate2: "2020/02/15"
}

// this will work
if ((obj.endDate1 >= obj.startDate2 && obj.startDate1 <= obj.endDate2) ||
  (obj.endDate2 >= obj.startDate1 && obj.startDate2 <= obj.endDate1)) {
  console.log('overlap detected')
}
aganda
  • 11
  • 2