Javascript Date comparison

  • Hari Narayanan
  • Graduate
  • Graduate
  • Hari Narayanan
  • Posts: 103

Post 3+ Months Ago

Hi all

How to compare 2 dates using Javascript?

[ Just like how we do it using VBScript datediff() function, but non-IE browsers wont parse VBScript ! ].
  • Dark Uncle
  • Beginner
  • Beginner
  • Dark Uncle
  • Posts: 46

Post 3+ Months Ago

Code: [ Select ]
<script language="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));

</script>
  1. <script language="JavaScript">
  2. var days = 0;
  3. var difference = 0;
  4. Christmas = new Date("December 25, 2005");
  5. today = new Date();
  6. difference = Christmas - today;
  7. days = Math.round(difference/(1000*60*60*24));
  8. </script>


Taken from http://codepunk.hardwar.org.uk/ajs07.htm
  • Hari Narayanan
  • Graduate
  • Graduate
  • Hari Narayanan
  • Posts: 103

Post 3+ Months Ago

Got it !!!
Heres the code .....

Code: [ Select ]
<html>
<head>
<title>Compare Dates</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<Script Language=Javascript>
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>
  1. <html>
  2. <head>
  3. <title>Compare Dates</title>
  4. <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
  5. <Script Language=Javascript>
  6. function CompareDates()
  7. {
  8.     var str1 = document.getElementById("Fromdate").value;
  9.     var str2 = document.getElementById("Todate").value;
  10.     var dt1  = parseInt(str1.substring(0,2),10);
  11.     var mon1 = parseInt(str1.substring(3,5),10);
  12.     var yr1  = parseInt(str1.substring(6,10),10);
  13.     var dt2  = parseInt(str2.substring(0,2),10);
  14.     var mon2 = parseInt(str2.substring(3,5),10);
  15.     var yr2  = parseInt(str2.substring(6,10),10);
  16.     var date1 = new Date(yr1, mon1, dt1);
  17.     var date2 = new Date(yr2, mon2, dt2);
  18.     if(date2 < date1)
  19.     {
  20.         alert("To date cannot be greater than from date");
  21.         return false;
  22.     }
  23.     else
  24.     {
  25.         alert("Submitting ...");
  26.         document.form1.submit();
  27.     }
  28. }
  29. </Script>
  30. </head>
  31. <body bgcolor="#FFFFFF" text="#000000">
  32. <form name="form1" method="post" action="">
  33. <input type="text" name="fromdate" id="fromdate" value="20/10/2005">
  34. <input type="text" name="todate" id="todate" value="19/10/2005">
  35. <input type="button" value="compare dates" onclick="CompareDates()">
  36. </form>
  37. </body>
  38. </html>
  • katana
  • Mastermind
  • Mastermind
  • User avatar
  • Posts: 2391
  • Loc: Edinburgh, Scotland

Post 3+ Months Ago

Javascript has the Date object, so if you'll need to create the two dates to compare, i.e.:
Code: [ Select ]
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
  1. var d1 = new Date(2005, 5, 1); // creates a new Date for the 1st June 2005
  2. var d2 = new Date(); // creates a new Date representing today


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

Code: [ Select ]
var milli_d1 = d1.getTime();
var milli_d2 = d2.getTime();
var diff = milli_d1 - milli_d2;
  1. var milli_d1 = d1.getTime();
  2. var milli_d2 = d2.getTime();
  3. var diff = milli_d1 - milli_d2;

In this case the difference will be negative, as d1 preceeds d2.
To work out the number of days in between the two dates:
Code: [ Select ]
var num_days = (((diff / 1000) / 60) / 60) / 24;


Not as easy as VBScript makes it ;)
  • joebert
  • Fart Bubbles
  • Genius
  • User avatar
  • Posts: 13504
  • Loc: Florida

Post 3+ Months Ago

Code: [ Select ]
1000*60*60*24

Tip wrote:
When math dealing with constants is discovered, replacing the equation with its result, in this case 86,400,000 , requires systems running the application to do less work.
  • George_Gambino
  • Student
  • Student
  • George_Gambino
  • Posts: 89

Post 3+ Months Ago

Comparing two dates in Javascript is all about using the Date() object, as alluded too in a couple of posts already. Here's a good article on how to check if a date entered via a form field is earlier than today's date :

http://www.ImageCowboy.com/articles/javascript_date_function_compare_two_dates.asp

Gambino
  • tjcrowder
  • Newbie
  • Newbie
  • tjcrowder
  • Posts: 5

Post 3+ Months Ago

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

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.)
  • joebert
  • Fart Bubbles
  • Genius
  • User avatar
  • Posts: 13504
  • Loc: Florida

Post 3+ Months Ago

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. :scratchhead: It sure would be nice if I knew what part of say, Firefox or Chrome source code I should look at to find out.
  • tjcrowder
  • Newbie
  • Newbie
  • tjcrowder
  • Posts: 5

Post 3+ Months Ago

@joebert:
Quote:
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.
Quote:
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:
Code: [ Select ]
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"
  1. var d1, d2;
  2. d1 = new Date(2010, 10, 1);
  3. d2 = new Date(2009, 10, 3);
  4. write("d1: " + d1);
  5. // Writes "Mon Nov 01 2010 00:00:00 GMT+0000 (GMT Standard Time)"
  6. write("d2: " + d2);
  7. // Writes "Tue Nov 03 2009 00:00:00 GMT+0000 (GMT Standard Time)"
  8. write(d1 > d2);
  9. // writes "true", d1 is in 2010, d2 is in 2009
  10. write(d1.toString() > d2.toString());
  11. // 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.)
--
T.J. Crowder
Independent Software Consultant
tj / crowder software / com
www crowdersoftware com
  • joebert
  • Fart Bubbles
  • Genius
  • User avatar
  • Posts: 13504
  • Loc: Florida

Post 3+ Months Ago

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. :D
  • tjcrowder
  • Newbie
  • Newbie
  • tjcrowder
  • Posts: 5

Post 3+ Months Ago

@joebert:
Quote:
Nice explaination, T.J.

Thanks!
Quote:
I'd like to say spec and implementation are sometimes different things...

Yeah. :D 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.
  • Psyborg
  • Born
  • Born
  • Psyborg
  • Posts: 1

Post 3+ Months Ago

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:

JAVASCRIPT Code: [ Select ]
   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);
   }
 
  1.    dat1 = new Date("Sep 24 2010 08:57:00");
  2.    dat2 = new Date("Sep 24 2010 08:57:00");
  3.    
  4.    if(dat1 == dat2)
  5.    {
  6.       alert('Dates are equal!\n'+dat1+'\n'+dat2);
  7.    } else {
  8.       alert('Dates are NOT equal!\n'+dat1+'\n'+dat2);
  9.    }
  10.  


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.
  • joebert
  • Fart Bubbles
  • Genius
  • User avatar
  • Posts: 13504
  • Loc: Florida

Post 3+ Months Ago

Code: [ Select ]
if(dt1-0 == dt2-0)


Similar to the style used in MySQL.
  • tjcrowder
  • Newbie
  • Newbie
  • tjcrowder
  • Posts: 5

Post 3+ Months Ago

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):

JAVASCRIPT Code: [ Select ]
if (d1.getTime() == d2.getTime()) {

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

JAVASCRIPT Code: [ Select ]
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
  • joebert
  • Fart Bubbles
  • Genius
  • User avatar
  • Posts: 13504
  • Loc: Florida

Post 3+ Months Ago

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.

JAVASCRIPT Code: [ Select ]
   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()));
  1.    var   stamps = {
  2.       s1: new Date(),
  3.       e1: new Date(),
  4.       s2: new Date(),
  5.       e2: new Date(),
  6.       s3: new Date(),
  7.       e3: new Date(),
  8.    };
  9.    
  10.    stamps.s1 = new Date();
  11.    for(var i = 0; i < 100000; i++)
  12.    {
  13.       if(+stamps.s1 == +stamps.e1) {}
  14.    }
  15.    stamps.e1 = new Date();
  16.    
  17.    stamps.s2 = new Date();
  18.    for(var i = 0; i < 100000; i++)
  19.    {
  20.       if(stamps.s2.getTime() == stamps.e2.getTime()) {}
  21.    }
  22.    stamps.e2 = new Date();
  23.    
  24.    stamps.s3 = new Date();
  25.    for(var i = 0; i < 100000; i++)
  26.    {
  27.       if(stamps.s3-0 == stamps.e3-0) {}
  28.    }
  29.    stamps.e3 = new Date();
  30.    
  31.    alert((stamps.e1.getTime() - stamps.s1.getTime()) + "\n" + (stamps.e2.getTime() - stamps.s2.getTime()) + "\n" + (stamps.e3.getTime() - stamps.s3.getTime()));
  • tjcrowder
  • Newbie
  • Newbie
  • tjcrowder
  • Posts: 5

Post 3+ Months Ago

joebert wrote:
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.)

Here's a quick-and-dirty test bed: jsbin dot com/ukaju4
--
T.J. Crowder
tj / crowder software / com

Post Information

  • Total Posts in this topic: 16 posts
  • Users browsing this forum: No registered users and 130 guests
  • You cannot post new topics in this forum
  • You cannot reply to topics in this forum
  • You cannot edit your posts in this forum
  • You cannot delete your posts in this forum
  • You cannot post attachments in this forum
 
 

© 1998-2014. Ozzu® is a registered trademark of Unmelted, LLC.