Asked
Updated
Viewed
278.9k times

How do you compare 2 dates using JavaScript?

With VBScript I would use the datediff function which returns the number of intervals between two dates. The syntax for the VBScript datediff function looks like this:

DateDiff(interval,date1,date2[,firstdayofweek[,firstweekofyear]])

This would return a number. For example, if the interval was months identified by the interval m, and if there were 9 months between the two dates, then the datediff function would return 9.

How can I do something similar with JavaScript? I am trying to compare two dates and then ensure that one date occurs after the other date.

  • 0
    Comparing two dates in JavaScript is all about using the Date() object, as alluded to in a couple of posts already. — George_Gambino
add a comment
0

12 Answers

  • Votes
  • Oldest
  • Latest
Answered
Updated

Below you could calculate the number of days between two dates using JavaScript:

var days = 0;
var difference = 0;

Christmas = new Date("December 25, 2005");

today = new Date();

difference = Christmas - today;

days = Math.round(difference/(1000*60*60*24));
add a comment
0
Answered
Updated

I was able to solve my problem with the following HTML and JavaScript. The code will gather the data inputted in the forms and then create two Date objects in JavaScript. After that, it is a simple comparison of the dates to determine if one date is actually occurring before or after the other date. In this case if date2 is less than date, then it will throw an alert error message that the To Date cannot be greater than the From Date.

<html>
<head>
<title>Compare Dates</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">

<script>
function CompareDates() 
{ 
    var str1  = document.getElementById("Fromdate").value;
    var str2  = document.getElementById("Todate").value;
    var dt1   = parseInt(str1.substring(0,2),10); 
    var mon1  = parseInt(str1.substring(3,5),10);
    var yr1   = parseInt(str1.substring(6,10),10); 
    var dt2   = parseInt(str2.substring(0,2),10); 
    var mon2  = parseInt(str2.substring(3,5),10); 
    var yr2   = parseInt(str2.substring(6,10),10); 
    var date1 = new Date(yr1, mon1, dt1); 
    var date2 = new Date(yr2, mon2, dt2); 

    if(date2 < date1) {
        alert("To date cannot be greater than from date");
            return false; 
	} else 	{ 
            alert("Submitting ...");
            document.form1.submit(); 
	} 
} 

</script>
</head>

<body bgcolor="#FFFFFF" text="#000000">
    <form name="form1" method="post" action="">
        <input type="text" name="fromdate" id="fromdate" value="20/10/2005">
        <input type="text" name="todate" id="todate" value="19/10/2005">
        <input type="button" value="compare dates" onclick="CompareDates()">
    </form>
</body>
</html>
add a comment
0
Answered
Updated

JavaScript has the Date object, so if you'll need to create the two dates to compare, i.e.:

var d1 = new Date(2005, 5, 1);  // creates a new Date for the 1st June 2005
var d2 = new Date(); // creates a new Date representing today

To compute the difference, convert both to their millisecond representations and subtract:

var milli_d1 = d1.getTime();
var milli_d2 = d2.getTime();
var diff = milli_d1 - milli_d2;

In this case the difference will be negative, as d1 precedes d2. To work out the number of days in between the two dates:

var num_days = (((diff / 1000) / 60) / 60) / 24;

Not as easy as VBScript makes it 😉

  • 0
    Regarding the use of 1000*60*60*24, when doing math and dealing with constants is discovered, replacing the equation with its result, in this case, 86400000, requires systems running the application to do less work. — joebert
add a comment
0
Answered
Updated

For the benefit of anyone else stumbling across this thread, most of the above respondents are working too hard. 😁

If you want to know if one date instance is earlier than another, just use the < operator, which is defined as comparing the primitive values of objects. The primitive value of a Date object is its milliseconds-since-The-Epoch value (aka Date#getTime), see sections 9.1 and 15.9 of the 3rd edition ECMA specification. Hence <, ==, and > work as you expect them to, no need for explicitly calling getTime().

Arithmetic is done the same way. Subtract one date from another date and the result is the difference in milliseconds. (Addition is a bit weird, since what you're adding is their Epoch values, so the result isn't going to mean much.)

  • 0
    Here I thought comparing two dates via <=> would invoke the toString method of the date object and end up comparing the strings returned. I'm still not sure whether that's what's actually happening. 🤔 It sure would be nice if I knew what part of say, Firefox or Chrome source code I should look at to find out. — joebert
add a comment
0
Answered
Updated

@joebert:

Here I thought comparing two dates via <=> would invoke the toString method of the date object and end up comparing the strings returned.

Nope, compares them via valueOf, which for Date is the same as getTime.

It sure would be nice if I knew what part of say, Firefox or Chrome source code I should look at to find out.

No need to sort through source code, the specification (ecma-international .org / publications / standards / Ecma-262.htm) is clear, you just have to cross-reference sections. Start with 11.8.5 ("The Abstract Relational Comparison Algorithm") that tells us the values will be compared using the [[ToPrimitive]] operation with the "hint" Number. Head over to section 9.1 ("ToPrimitive") and it tells us that for Objects, [[ToPrimitive]] just passes through to [[DefaultValue]], passing on the hint. Head over to 8.12.8 ("DefaultValue (hint)") and it tells us if the hint is Number and the object has a valueOf, it'll use valueOf. So check out Date's valueOf (15.9.5.8 ) and it says it returns "this time value" which is the spec's way of saying the number of milliseconds since The Epoch (read the introduction to the Date object [15.9.1, 15.9.1.1] to verify that). Conveniently, the very next section (15.9.5.9) is getTime, which says the same thing.

(Those section numbers are from the new 5th edition spec, but the ECMA were very smart and avoided changing section numbers where they could. In the 3rd edition spec, the only different one is that "[[DefaultValue]] (hint)" is 8.6.2.6 instead of 8.12.8.)

It's also trivial to prove this experimentally:

var d1, d2;

d1 = new Date(2010, 10, 1);
d2 = new Date(2009, 10, 3);

write("d1: " + d1);
// Writes "Mon Nov 01 2010 00:00:00 GMT+0000 (GMT Standard Time)"
write("d2: " + d2);
// Writes "Tue Nov 03 2009 00:00:00 GMT+0000 (GMT Standard Time)"

write(d1 > d2);
// writes "true", d1 is in 2010, d2 is in 2009
write(d1.toString() > d2.toString());
// writes "false", d1's string starts with an "M", d2's with a "T"; "M" < "T"

As you can see, it's not using toString when relationally comparing Date instances.

(In the above, write is whatever output mechanism you want to use; it should be sure to treat what it gets as a String, or it may output -1 instead of true and 0 instead of false -- comes to the same thing, but it's less clear.)

add a comment
0
JO
184 4
Answered
Updated

I'd like to say spec and implementation are sometimes different things, but it's tough to argue with that post. Nice explaination, T.J. 😁

add a comment
0
Answered
Updated

@joebert:

Nice explaination, T.J.

Thanks!

I'd like to say spec and implementation are sometimes different things...

Yeah. 😁 That's where the experiment comes in. I usually like to know what it's supposed to do, then check that it really does it.

-- T.J.

add a comment
0
Answered
Updated

Ok, thanks for all the comments above, they're all very well thought out and useful.

I do have a bit of a problem though, using the [==] operator. Here is a forinstance:

	dat1 = new Date("Sep 24 2010 08:57:00");
	dat2 = new Date("Sep 24 2010 08:57:00");

	if(dat1 == dat2)
	{
		alert('Dates are equal!\n'+dat1+'\n'+dat2);
	} else {
		alert('Dates are NOT equal!\n'+dat1+'\n'+dat2);
	}

The message is puzzling...

"Dates are NOT equal"
"Fri Sep 24 2040 08:57:00 GMT-700 (Pacific Daylight Time)"
"Fri Sep 24 2040 08:57:00 GMT-700 (Pacific Daylight Time)"

Any idea what's going on? This happens in Chrome 7 & IE.

add a comment
0
JO
184 4
Answered
Updated
if(dt1-0 == dt2-0)

Similar to the style used in MySQL.

add a comment
0
Answered
Updated

The reason is that the equality operator (==) is not comparing the same thing that the relational operators like < and > compare.

When you use == to compare two "variables" that refer to objects, the result is true if the variables point to the same object, and false if they don't, with the exception of Number and String instances, which have special handling. (See Section 11.9.3 of the spec.)

In contrast, the relational operators try to get primitive values for the objects (if the objects have primitive values) and then compare those instead. Date objects have a primitive value (the number of milliseconds since The Epoch) and so the relational operators compare those values.

A consequence of this is that (confusingly!) two Date instances can be != even though they are neither < or > each other. And that's exactly what you have in your example, two different objects that represent the same moment in time. (Well, at least, you're very very likely to have them representing the same moment in time, although technically you do create one and then create the other, so they could be a millisecond or two off.)

Here's a live example: jsbin dot com/ikude4/2

You can easily compare two date objects in the way you wanted to. I usually do it the long way, by explicitly calling getTime (which returns the number):

if (d1.getTime() == d2.getTime()) {

...because it's completely clear what I'm doing, but there's a trickier way that some people prefer:

if (+d1 == +d2) {

The plus sign (+) does the same "get primitive numeric value" thing that the relational operators do, and so the above compares the numbers rather than the object instances. Here's the example above using + instead of getTime(): jsbin dot com/ikude4

HTH,

T.J. Crowder
Independent Software Consultant
tj / crowder software / com

add a comment
0
JO
184 4
Answered
Updated

Though I don't see a browser ever doing this often enough to make a noticeable difference in an application, the results I'm getting from the following little test were interesting.

I expected the arithmetic version to be faster than the function call. However it seems the function call is the fastest of the three, where I'm sitting.

	var	stamps = {
		s1: new Date(),
		e1: new Date(),
		s2: new Date(),
		e2: new Date(),
		s3: new Date(),
		e3: new Date(),
	};

	stamps.s1 = new Date();
	for(var i = 0; i < 100000; i++)
	{
		if(+stamps.s1 == +stamps.e1) {}
	}
	stamps.e1 = new Date();

	stamps.s2 = new Date();
	for(var i = 0; i < 100000; i++)
	{
		if(stamps.s2.getTime() == stamps.e2.getTime()) {}
	}
	stamps.e2 = new Date();

	stamps.s3 = new Date();
	for(var i = 0; i < 100000; i++)
	{
		if(stamps.s3-0 == stamps.e3-0) {}
	}
	stamps.e3 = new Date();

	alert((stamps.e1.getTime() - stamps.s1.getTime()) + "\n" + (stamps.e2.getTime() - stamps.s2.getTime()) + "\n" + (stamps.e3.getTime() - stamps.s3.getTime()));
add a comment
0
Answered
Updated

Though I don't see a browser ever doing this often enough to make a noticeable difference in an application, the results I'm getting from the following little test were interesting.

I expected the arithmetic version to be faster than the function call. However it seems the function call is the fastest of the three, where I'm sitting.

That is interesting. But as always, it's virtually impossible to generalize performance optimizations with JavaScript across implementations. What's faster on one implementation is often slower on another. Even such simple and obvious things as counting backward to zero [for (i = 100; i > 0; --i)] rather than forward to a limit [for (i = 0; i < 100; ++i)], which you would think would always be faster because of the very optimizable "greater than zero" comparison, can't be relied upon.

But your getTime results are interesting. On both Chrome and Firefox for Linux, in my tests, getTime is markedly Faster than the other options (I expect they're inlining the call, and since there's no conditional checks required as with converting to number...), whereas on IE6 and IE8 on Windows, that's the slowest option. (And Opera for Linux shows a marked preference for the + sign.)

add a comment
0