1

I'm wondering if anyone has a JavaScript function to return the number of months and days between 2 dates? For example, if passed 01/01/2013 and 03/01/2015 (UK Date format) It would return 24 Months 2 Days. I have the months part, but I'm struggling with the days piece. There are 2 date fields on my form on dd/mm/yyyy format. here's the code I have so far:

function calculateDateDifference(){
var startDateValue=document.forms[0].StartDate.value;
var endDateValue=document.forms[0].EndDate.value;

var startDateArray=startDateValue.split("/");
var endDateArray=endDateValue.split("/");

var startDate= new Date(startDateArray[2], startDateArray[1], startDateArray[0]);
var endDate= new Date(endDateArray[2], endDateArray[1], endDateArray[0]);

var diffYears = endDate.getFullYear()-startDate.getFullYear();
var diffMonths = endDate.getMonth()-startDate.getMonth();
var diffDays = endDate.getDate()-startDate.getDate();

var months = ((diffYears*12) + diffMonths);
if (diffDays<0){
    months=months-1;
    }
alert(months + " months");
}

Thanks in advance, Niall.

nelsie
  • 65
  • 2
  • 7
  • check out http://www.datejs.com/ – Walter Brand Jan 03 '13 at 09:22
  • Sorry but I think your approach to this problem is faulty. One problem you'll encounter is that months are inconsistent. What does 1 month mean? 31 days? 30? 28? That doesn't allow you much precision. Perhaps you should rethink your approach and question whether or not it's useful/necessary to calculate the number of months between the dates. – IsisCode Jan 03 '13 at 11:01

2 Answers2

0

This function will calculate the number of days between two dates in UK (little Endian) format.

​function subtractDates(firstDate, secondDate){
        var fdObj, sdObj;
        firstDate = littleToMiddleEndian(firstDate);
        secondDate = littleToMiddleEndian(secondDate);
        function littleToMiddleEndian(led){
            var a = led.split("/")
            return [a[1],a[0],a[2]].join("-");
        }
        fdObj = new Date(firstDate);
        sdObj = new Date(secondDate);
        return sdObj-fdObj/86400000;
    }
    var daysBetween = subtractDates("10/01/12","17/01/12");
    console.log(daysBetween);

First, it uses an inner function to convert the dates from little Endian format (dd-mm-yy) to the middle endian format (mm-dd-yy) required by the Date object. Then it creates two Date objects and subtracts one from the other, then divides by 86400000 (the number of miliseconds in a day) which results in an integer representing the number of days between the two dates.

IsisCode
  • 2,490
  • 18
  • 20
  • Thanks @IsisCode. I have added my code so far and have something quite similar for monthe. I'm working on the days part now – nelsie Jan 03 '13 at 10:43
  • The "middle endian format" is not required by the Date constructor at all. Until ES5, parsing of strings was implementation dependent. The only string format specified for ECMA–262 is a version of the [ISO8601 long format](http://www.ecma-international.org/ecma-262/5.1/#sec-15.9.1.15). Since you split the date into it's components, far better to just use the parts: `return new Date(a[2], --a[1], a0)` to get a standards compliant, cross browsers function that doesn't depend on browser quirks. – RobG Mar 25 '13 at 00:49
0

Thanks to the answer by @Zazerat on this post

I have come up with a solution. @Jazerat provided a cut down version of JSDate which I included to easily allow for month adjustment on a Date. Here's the final code:

    Date.isLeapYear = function (year) { 
    return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0)); 
};

Date.getDaysInMonth = function (year, month) {
    return [31, (Date.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
};

Date.prototype.isLeapYear = function () { 
    var y = this.getFullYear(); 
    return (((y % 4 === 0) && (y % 100 !== 0)) || (y % 400 === 0)); 
};

Date.prototype.getDaysInMonth = function () { 
    return Date.getDaysInMonth(this.getFullYear(), this.getMonth());
};

Date.prototype.addMonths = function (value) {
    var n = this.getDate();
    this.setDate(1);
    this.setMonth(this.getMonth() + value);
    this.setDate(Math.min(n, this.getDaysInMonth()));
    return this;
};

function daysInMonth(month,year) {
    return new Date(year, month, 0).getDate();
}


function calculateLeasePeriod(){

var startDateValue=document.forms[0].StartDate.value;
var endDateValue=document.forms[0].EndDate.value;

if (endDateValue!="" && startDateValue!=""){

    var startDateArray=startDateValue.split("/");
    var endDateArray=endDateValue.split("/");

    var startDate= new Date(startDateArray[2], startDateArray[1], startDateArray[0]);
    var endDate= new Date(endDateArray[2], endDateArray[1], endDateArray[0]);

    var diffYears = endDate.getFullYear()-startDate.getFullYear();
    var diffMonths = endDate.getMonth()-startDate.getMonth();
    var diffDays = endDate.getDate()-startDate.getDate();

    var months = ((diffYears*12) + diffMonths);
    if (diffDays<0){
        months=months-1;
        var adjStartDate = startDate.addMonths(months);
        diffDays = endDate.getDate()-adjStartDate.getDate();
        if (diffDays<0){
            diffDays=daysInMonth(adjStartDate.getMonth(), adjStartDate.getYear())+ diffDays;
            }
        }

    $("#PrimaryLeasePeriod").html(months + " months and " + diffDays + " days");

    }else{
        $("#PrimaryLeasePeriod").html("");
    }
}

I hope someone else finds this useful!

Community
  • 1
  • 1
nelsie
  • 65
  • 2
  • 7