...

View Full Version : Resolved Date comparison in months



longman
07-20-2009, 06:41 AM
Hi All,

Apologies if this has been done, I searched and searched but could not find a solution. (if anyone has found it, please link to the thread).

What I'd like to know is how to compare 2 user input dates (say Date1 and Date2) in dd/mm/yyyy format, to ensure that Date2 is at least 2 months after Date1. Comparing them in days is simple but I'm not sure where to start on months, taking into account differing number of days per month and leap years.

e.g 01/01/2009 - 28/02/2009 would equal 2 months.

Any help would be greatly appreciated.

Cheers!

Philip M
07-20-2009, 08:02 AM
Try this:-


<form name = "myform">
Enter First Date DD/MM/YYYY <input type = "text" name = "date1" id = "date1"><br>
Enter Second Date DD/MM/YYYY <input type = "text" name = "date2" id = "date2"><br><br>
Second date must be at least two months ahead of first date
<br><br>

<input type = "button" value = "Check Date" onclick = "checkit()">
</form>

<script type = "text/javascript">

function checkit() {

var d1 = document.myform.date1.value.split("/");
var yr = d1[2];
var mm = d1[1]-1;
var dy = d1[0];
var OK1 = checkValidDate(yr,mm,dy);
if ((yr < 1900 || yr > 2100)) {OK1 = false}

var d2 = document.myform.date2.value.split("/");
yr = d2[2];
mm = d2[1]-1;
dy = d2[0];
var OK2 = checkValidDate(yr,mm,dy);
if ((yr < 1900 || yr > 2100)) {OK2 = false} // year must be 1900 - 2100

if ((!OK1) || (!OK2)) {
alert ("Invalid dates\(s\) or incorrect format! Please try again.");
document.myform.date1.value = "";
document.myform.date2.value = "";
return false;
}

var firstDate = new Date(d1[2],d1[1]-1,d1[0]); // note month must be 0-11!! Also note USA date format
var secondDate = new Date(d2[2],d2[1]-3,d2[0]); // future month -1 -2
var secondDate2 = new Date(d2[2],d2[1]-1,d2[0]); // actual month -1

if (secondDate2 < firstDate) {
alert ("Second date is before first date! Please re-enter.");
document.myform.date1.value = "";
document.myform.date2.value = "";
return false;
}
else if (secondDate >= firstDate) {
alert ("Second date is two months or more ahead of first date");
}
else {
alert ("Second date is less than two months ahead of first date");
}

}

function checkValidDate(yr,mm,dy) {

var nd = new Date();
nd.setFullYear(yr,mm,dy); // YYYY,MM(0-11),DD
var ndmm = nd.getMonth();
if (ndmm != mm) {
return false;
}
else {
return true;
}

}

</script>

As usual the lion's share of the script is validation.

I would consider that 01/01/2009 - 28/02/2009 would equal LESS THAN 2 FULL months. Two FULL months have elapsed on 01/03/2009.


"Never attribute to malice that which can be adequately explained by stupidity." - Hanlon's razor

12 Pack Mack
07-20-2009, 01:27 PM
longman:


The following code returns true for:
31/07/2009 - 30/09/2009 : two calendar months
31/12/2009 - 28/2/2010 : two calendar months

The text in the preceding post wrongly returns false for those and every other "end of the month" date sets.



<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>None</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script type="text/javascript">

function verify(nField){

var splitDate = nField.value.split("/");
var refDate = new Date(splitDate[2],splitDate[1]-1,splitDate[0]);
if (refDate.getDate() != splitDate[0] || (!/^20/.test(splitDate[2])))
{
return false;
}
nField.value = nField.value.replace(/^(\d{1}\/)/,"0$1").replace(/(\d{2}\/)(\d{1}\/)/,"$10$2");
return refDate;
}

function validate(nForm){

var refDate = "";
var nYears = 0;
var nMonths = 0;
var nDays = 0;
var startDate = verify(nForm['startDate']);
if (startDate){var endDate = verify(nForm['endDate'])}
if (startDate && endDate)
{
if (startDate >= endDate)
{
alert('End date must be later than Start date');
return false;
}
refDate = startDate;
var startDateEOM = new Date(refDate.getFullYear(),refDate.getMonth()+1,refDate.getDate()-refDate.getDate()).getDate();
refDate = new Date(refDate.getFullYear(),refDate.getMonth()-1,1);
for (i=-1; refDate<endDate; i++)
{
refDate = new Date(refDate.getFullYear(),refDate.getMonth()+1,1);
refDate = new Date(refDate.getFullYear(),refDate.getMonth()+1,refDate.getDate()-1);
}
nMonths = i;
var endDateEOM = refDate;
if (startDate.getDate() > endDate.getDate() && endDate.getDate() != refDate.getDate()){nMonths--}
nYears = parseInt(nMonths/12);
nMonths = nMonths-(nYears*12);
var prevEOM = new Date(refDate.getFullYear(),refDate.getMonth()-1,1)
prevEOM = new Date(prevEOM.getFullYear(),prevEOM.getMonth()+1,prevEOM.getDate()-1)
if (nMonths == 0 && nYears == 0)
{
nDays = Math.round((endDate-startDate)/86400000);
}
if (startDate.getDate() < endDate.getDate())
{
nDays = endDate.getDate()-startDate.getDate();
}
if (startDate.getDate() > endDate.getDate())
{
nDays = startDateEOM-startDate.getDate();
nDays += Math.round((endDate-prevEOM)/86400000);
if (startDateEOM < prevEOM && startDate.getDate() != startDateEOM)
{
nDays += prevEOM.getDate()-startDateEOM;
}
}
if (startDate.getDate() == startDateEOM && endDate.getDate() == endDateEOM.getDate())
{
nDays = 0;
}
}
if (!startDate)
{
alert('Invalid Start Date')
nForm['startDate'].value = "";
nForm['startDate'].focus();
return false;
}
else if (!endDate)
{
alert('Invalid End Date')
nForm['endDate'].value = "";
nForm['endDate'].focus();
return false;
}
if (nMonths >=2)
{
// delete the following line after testing:
alert('Calendar Months, Days and Years Apart:\nM:D:Y\n' + nMonths + ':' + nDays + ':' + nYears)
alert('Thank you for your submission');
return true;
}
else {
alert('End date must be at least two calendar\nmonths ahead of the Start date');
return false;
}
}

function init(){

var nForm = document.forms[0];
nForm.onsubmit = function()
{
return validate(nForm);
}
}

navigator.appName == "Microsoft Internet Explorer" ? attachEvent('onload', init, false) : addEventListener('load', init, false);

</script>
<style type="text/css">

body {margin-top: 60px;}
label {font-family: tahoma; font-size: 11pt; display: block;}
.data {text-align: right;}

</style>
</head>
<body>
<form action="" method="post">

<label>Start Date: (dd/mm/yyyy): <input type="text" name="startDate" size="10" class="data" value="31/7/2009"></label>
<label>End Date: (dd/mm/yyyy): <input type="text" name="endDate" size="10" class="data" value="30/9/2009"></label>

<input type="submit" name="submit" value="Submit" class="submitBtn">

</form>
</body>
</html>

Philip M
07-20-2009, 01:48 PM
The OP requires

to ensure that Date2 is at least 2 months after Date1. I interpret that to mean two CLEAR months. That is, one day after the first date + 2 months. If you were disqualified from driving for two months from 31/07/2009 then you would not be able to drive again before 01/10/2009. The disqualification expires at 0000 hrs on 01/10/2009, not on 30/09/2009. But it is up to the OP to clarify that.

As I often say, there is usually more than one way to kill a cat. I don't see that your method is any better, quicker, shorter, more effective, more accurate or whatever than mine. Just the same as with your doppelgangers Cranford, Henley and Co.

In fact I find that your script wrongly returns false for 01/01/2009 - 28/02/2009 which is what the OP asked for. :p:p At least mine works reliably on my definition of "at least two months".

He who posts last, thinks slowest. :D:D

longman
07-20-2009, 10:31 PM
thank you both for your replies. I now have exactly what I need for now and the future. The thing I love most about JS is the multitude of ways to achieve similar results!!



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum