Robust way to compare multiple dates - javascript

In a scenario, where the user can select a date ("from" date), along with the current date ("to" date), what is the best way to compare multiple (at least two) dates?
Assuming the incoming dates are a string with the format MM-DD-YYYY, consider the following comparison:
a = new Date("02-21-2018") // user "from" date
b = new Date() // current "to" date
b = b.setHours(0,0,0,0) // trim the time to compare just the dates
b = new Date(b) // converting back to the Date type
console.log("- :", a - b) // 0 (correct)
console.log("== :", a == b) // false (wrong)
console.log("<= :", a <= b) // true (correct)
console.log(">= :", a >= b) // true (correct)
console.log("value :", a.valueOf() == b.valueOf()) // true (correct)
Clearly there is a problem with comparing it directly using ==. So what is the best alternative? Would anything be different if we have several (not just two) dates?
Also when comparing two dates like new Date("02-21-2018") <= new Date() can a time zone affect the outcome?

You need to use the .getTime() method on your date objects.
Checking equality on the date objects doesn't work.
a = new Date("02-21-2018") // user "from" date
b = new Date() // current "to" date
b = b.setHours(0,0,0,0) // trim the time to compare just the dates
b = new Date(b) // converting back to the Date type
a = a.getTime();
b = b.getTime();
console.log("- :", a - b)
console.log("== :", a == b)
console.log("<= :", a <= b)
console.log(">= :", a >= b)
console.log("value :", a.valueOf() == b.valueOf())
Here is a similar subject:
Compare two dates with JavaScript
About the timezone,
I am not sure about what you want to do, but :
The method .getTimezoneOffset() can be used on your date objects to return their offsets.
As javascript runs in your browser on your computer, I guess the time zone of your new Date() will be affected by your "TimezoneOffset".

Related

cannot compare dates for some reason [duplicate]

When comparing date objects in Javascript I found that even comparing the same date does not return true.
var startDate1 = new Date("02/10/2012");
var startDate2 = new Date("01/10/2012");
var startDate3 = new Date("01/10/2012");
alert(startDate1>startDate2); // true
alert(startDate2==startDate3); //false
How could I compare the equality of these dates? I am interested in utilizing the native Date object of JS and not any third party libraries since its not appropriate to use a third party JS just to compare the dates.
That is because in the second case, the actual date objects are compared, and two objects are never equal to each other. Coerce them to number:
alert( +startDate2 == +startDate3 ); // true
If you want a more explicity conversion to number, use either:
alert( startDate2.getTime() == startDate3.getTime() ); // true
or
alert( Number(startDate2) == Number(startDate3) ); // true
Oh, a reference to the spec: §11.9.3 The Abstract Equality Comparison Algorithm which basically says when comparing objects, obj1 == obj2 is true only if they refer to the same object, otherwise the result is false.
Compare dates using getTime() returning number of milliseconds from epoch (i.e. a number):
var startDate1 = new Date("02/10/2012");
var startDate2 = new Date("01/10/2012");
var startDate3 = new Date("01/10/2012");
alert(startDate1.getTime() > startDate2.getTime()); // true
alert(startDate2.getTime() == startDate3.getTime()); //true
Also consider using Date constructor taking explicit year/month/date number rather then relying on string representation (see: Date.parse()). And remember that dates in JavaScript are always represented using client (browser) timezone.
You do not need to use the getTime method- you can subtract a date object from another date object. It will return the milliseconds difference(negative, if the second is a later date)
var startDate1 = new Date("02/10/2012");
var startDate2 = new Date("01/10/2012");
var diff= (startDate1 -startDate2)
// evaluates to 0 if the dates have the same timestamp
you can compare the actual milliseconds :
alert(startDate2.getTime() === startDate3.getTime());
tl;dr
Use date.getTime() for comparisons.
Based on my testing, it was at least 25% than the next fastest alternative (date.valueOf()).
Details
Came across this in 2022. As others have already said, comparing like date1.getTime() === date2.getTime() is the way to go.
Someone else shared a jsperf link in an answer that seems broken for me right now, so decided to add some performance comparison of my own.
I created two arrays containing 1000 dates each. All dates will naturally be different instances (meaning direct === checks will fail), so what this benchmark does, is test what the fastest way is to convert a date to a primitive.
Here's the test data:
const data1 = Array.from({length: 1000}, () => new Date())
const data2 = Array.from({length: 1000}, () => new Date())
And here are the test cases (there's more in the link below):
// 1
data1.forEach((d1, i) => d1.getTime() === data2[i].getTime());
// 2
data1.forEach((d1, i) => d1.valueOf() === data2[i].valueOf());
// 3
data1.forEach((d1, i) => Number(d1) === Number(data2[i]));
// 4
data1.forEach((d1, i) => d1.toISOString() === data2[i].toISOString());
Result (use date.getTime())
Not a surprise that a date.getTime() conversion is much faster. It's around 25% faster than date.valueOf(), and between 10x and 100x faster than everything else (as far as I've checked).
Additionally, introducing optional chaining slowed the best case by almost 10% for me. Found that interesting. date.valueOf() also slowed down by 5% compared to its non optional chaining counterpart.
data1.forEach((d1, i) => d1?.getTime() === data2[i]?.getTime());
Benchmark link: here
Here's an image, in case the above link breaks at some point in the future.
You can also use the function valueOf()
var startDate1 = new Date("02/10/2012").valueOf();
var startDate2 = new Date("01/10/2012").valueOf();
var startDate3 = new Date("01/10/2012").valueOf();
alert(startDate1>startDate2); // 1326150000000 > 1328828400000 true
alert(startDate2==startDate3); // 1328828400000 > 1326150000000 false
One more way of comparing two dates would be converting dates to timestamps using "+" operator before the date.
So, let's say we have two dates:
const dateOne = new Date("10 January 1986")
const dateTwo = new Date("10 December 2020")
if(+dateOne == +dateTwo){
//do something
}
and so on.
This is really handy if you are sorting date objects too as you can use this in the sorting callback function.

Comparison of dates showing unexpected results?

A really simple question. Are these two dates different:
2020-09-02T00:00:00.000+00:00 and 2020-09-02T15:39:00+04:00
I mean if I compare them will I get true or false.
The date I am retrieving from the backend (MongoDB) is 2020-09-02T00:00:00.000+00:00 and the one I am passing in the request body is 2020-09-02T15:39:00+04:00. The result I am getting is false when comparing.
If they are not the same, how do I convert this date 2020-09-02T15:39:00+04:00 into the DB format. I only want the dates to be checked not the time. TIA
You can parse the strings to Date objects and then compare the dateStrings.
toDateString returns the date portion of a Dateobject as a readable string.
const date1 = new Date("2020-09-02T00:00:00.000+00:00");
const date2 = new Date("2020-09-02T15:39:00+04:00");
function compareDates(date1, date2) {
return date1.toDateString() === date2.toDateString();
}
compareDates(date1, date2); //true
But since you're handling different timezones I would suggest to use other methods.
const date1 = new Date("2020-09-02T00:00:00.000+00:00");
const date2 = new Date("2020-09-02T15:39:00+04:00");
function compareDates(date1, date2) {
return date1.getUTCFullYear() === date2.getUTCFullYear() &&
date1.getUTCMonth() === date2.getUTCMonth() &&
date1.getUTCDate() === date2.getUTCDate();
}
compareDates(date1, date2); //true
the getUTC... methods return the year, month or day according to universal time.

how to use findIndex javascript method with date object? [duplicate]

When comparing date objects in Javascript I found that even comparing the same date does not return true.
var startDate1 = new Date("02/10/2012");
var startDate2 = new Date("01/10/2012");
var startDate3 = new Date("01/10/2012");
alert(startDate1>startDate2); // true
alert(startDate2==startDate3); //false
How could I compare the equality of these dates? I am interested in utilizing the native Date object of JS and not any third party libraries since its not appropriate to use a third party JS just to compare the dates.
That is because in the second case, the actual date objects are compared, and two objects are never equal to each other. Coerce them to number:
alert( +startDate2 == +startDate3 ); // true
If you want a more explicity conversion to number, use either:
alert( startDate2.getTime() == startDate3.getTime() ); // true
or
alert( Number(startDate2) == Number(startDate3) ); // true
Oh, a reference to the spec: §11.9.3 The Abstract Equality Comparison Algorithm which basically says when comparing objects, obj1 == obj2 is true only if they refer to the same object, otherwise the result is false.
Compare dates using getTime() returning number of milliseconds from epoch (i.e. a number):
var startDate1 = new Date("02/10/2012");
var startDate2 = new Date("01/10/2012");
var startDate3 = new Date("01/10/2012");
alert(startDate1.getTime() > startDate2.getTime()); // true
alert(startDate2.getTime() == startDate3.getTime()); //true
Also consider using Date constructor taking explicit year/month/date number rather then relying on string representation (see: Date.parse()). And remember that dates in JavaScript are always represented using client (browser) timezone.
You do not need to use the getTime method- you can subtract a date object from another date object. It will return the milliseconds difference(negative, if the second is a later date)
var startDate1 = new Date("02/10/2012");
var startDate2 = new Date("01/10/2012");
var diff= (startDate1 -startDate2)
// evaluates to 0 if the dates have the same timestamp
you can compare the actual milliseconds :
alert(startDate2.getTime() === startDate3.getTime());
tl;dr
Use date.getTime() for comparisons.
Based on my testing, it was at least 25% than the next fastest alternative (date.valueOf()).
Details
Came across this in 2022. As others have already said, comparing like date1.getTime() === date2.getTime() is the way to go.
Someone else shared a jsperf link in an answer that seems broken for me right now, so decided to add some performance comparison of my own.
I created two arrays containing 1000 dates each. All dates will naturally be different instances (meaning direct === checks will fail), so what this benchmark does, is test what the fastest way is to convert a date to a primitive.
Here's the test data:
const data1 = Array.from({length: 1000}, () => new Date())
const data2 = Array.from({length: 1000}, () => new Date())
And here are the test cases (there's more in the link below):
// 1
data1.forEach((d1, i) => d1.getTime() === data2[i].getTime());
// 2
data1.forEach((d1, i) => d1.valueOf() === data2[i].valueOf());
// 3
data1.forEach((d1, i) => Number(d1) === Number(data2[i]));
// 4
data1.forEach((d1, i) => d1.toISOString() === data2[i].toISOString());
Result (use date.getTime())
Not a surprise that a date.getTime() conversion is much faster. It's around 25% faster than date.valueOf(), and between 10x and 100x faster than everything else (as far as I've checked).
Additionally, introducing optional chaining slowed the best case by almost 10% for me. Found that interesting. date.valueOf() also slowed down by 5% compared to its non optional chaining counterpart.
data1.forEach((d1, i) => d1?.getTime() === data2[i]?.getTime());
Benchmark link: here
Here's an image, in case the above link breaks at some point in the future.
You can also use the function valueOf()
var startDate1 = new Date("02/10/2012").valueOf();
var startDate2 = new Date("01/10/2012").valueOf();
var startDate3 = new Date("01/10/2012").valueOf();
alert(startDate1>startDate2); // 1326150000000 > 1328828400000 true
alert(startDate2==startDate3); // 1328828400000 > 1326150000000 false
One more way of comparing two dates would be converting dates to timestamps using "+" operator before the date.
So, let's say we have two dates:
const dateOne = new Date("10 January 1986")
const dateTwo = new Date("10 December 2020")
if(+dateOne == +dateTwo){
//do something
}
and so on.
This is really handy if you are sorting date objects too as you can use this in the sorting callback function.

Why Date comparison is showing weird behavior in javascript?

When I'm working with date comparison in javascript, in the browser console I did perform the following operations.
new Date() >= new Date() returned true
new Date() <= new Date() returned true
this looked good as I thought both are equal, if I was correct then
new Date() == new Date() should returns true
Interestingly it returned false. Then I performed below operations as well
new Date() > new Date() returned false
new Date() < new Date() returned false
new Date() != new Date() returns true
which was also fine with my assumption.
If both the new Date() s were returning same time then == should return true along with the >= and <=, other wise either of > or < should return ture as != returning true.
Following table consists expected results and actual results for different cases.
Why is the ACTUAL results column not following any of its preceding columns?
Use Date.getTime to compare the timestamp, otherwise you are simply comparing the objects, which we know aren't the same.
var d1 = new Date(),
d2 = new Date();
function fullCompare(a, b) {
console.log(a == b, a <= b, a >= b, a < b, a > b);
}
fullCompare(d1, d2);
fullCompare(d1.getTime(), d2.getTime());
Check for equality like you're doing compares the references to the objects. To compare the actual values of the objects themselves, the most common practice is to call getTime() method, which will return the number of milliseconds since 1970-01-01 00:00:00 UTC.
Therefore, the following code will return true:
(new Date()).getTime() == (new Date()).getTime()

Compare dates javascript

I need to validate different date's with some javascript(jquery).
I have a textbox with, the inputmask from jquery (http://plugins.jquery.com/plugin-tags/inputmask). The mask that i use is "d/m/y".
Now i have set up a CustomValidator function to validate the date.
I need 2 functions. One to check if the given date is greater then 18 years ago. You must be older then 18 year.
One function to check if the date is not in the future. It can only in the past.
The function are like
function OlderThen18(source, args) {
}
function DateInThePast(source, args) {
}
As you know the value you get back with args.Value is 27/12/1987 .
But how can i check this date in the functions? So that i can set args.IsValid to True or False.
I tried to parse the string(27/12/1987) that i get back from the masked textbox to a date but i get always a value back like 27/12/1988.
So how could I check the given dates with the other dates?
The simple way is to add 18 years to the supplied date and see if the result is today or earlier, e.g.:
// Input date as d/m/y or date object
// Return true/false if d is 18 years or more ago
function isOver18(d) {
var t;
var now = new Date();
// Set hours, mins, secs to zero
now.setHours(0,0,0);
// Deal with string input
if (typeof d == 'string') {
t = d.split('/');
d = new Date(t[2] + '/' + t[1] + '/' + t[0]);
}
// Add 18 years to date, check if on or before today
if (d.setYear && d.getFullYear) {
d.setYear(d.getFullYear() + 18);
}
return d <= now;
}
// For 27/4/2011
isOver18('27/4/2011'); // true
isOver18('26/4/2011'); // true
isOver18('28/4/2011'); // false
try this to start:
var d = new Date(myDate);
var now = new Date();
if ((now.getFullYear() - d.getFullYear()) < 18) {
//do stuff
}
The javascript date object is quite flexible and can handle many date strings.
You can compare two Date objects or use the Date interface methods, such as getSeconds() of getFullYear() in order to deduce useful data regarding the date.
See Date object reference formore details.
You'll need to construct, modify and compare Date objects - something like this:
// str should already be in dd/mm/yyyy format
function parseDate(str) {
var a = str.split('/');
return new Date(parseInt(a[2], 10), // year
parseInt(a[1], 10) - 1, // month, should be 0-11
parseInt(a[0], 10)); // day
}
// returns a date object for today (at midnight)
function today() {
var date = new Date();
date.setHours(0, 0, 0);
return date;
}
function DateInThePast(str) {
// date objects can be compared like numbers
// for equality (==) you'll need to compare the value of date.getTime()
return parseDate(str) < today();
}
function OlderThan18(str) {
// left as an exercise for the reader :-)
}

Categories

Resources