Javascript DateDiff Bug Fix

Interval Day Hour Minute Second
Date 1:
Date 2:
Results: 

IMPORTANT 01/01/01 = 01/01/1901 NOT 01/01/01 BCE. I suggest using 4 digit years to avoid confusion.

This is a Javascript DateDiff function I wrote back in 2007. I was bored one day and wanted an accurate DateDiff function because the one native to javascript is bugged.

I took great care to make sure the script works as expected but it's possible I made a mistake somewhere. Run a few tests on it and if you get the results you expect its probably going to work for you.

It calculates the time span in days, hours, minutes or seconds that have passed from 9999 BCE until 9999 AD.

I could implement my javascript library for dealing with "infinitely" large numbers but I haven't gotten around to it yet. This would circumvent the limitations of javascript and would allow us to calculate very large dates so I'll probably do it eventually.

It takes leap years into consideration. In addition to the standard leap years: 1 B.C. = 0, 9 B.C. = 8, 101 B.C = 100, etc, according to the astronomical system and are all leap years.

This code was hand written by me and is free for you to use in any way you would like. I used wikipedia and a few other pages as my source for all the rules. It would be cool if you left the comment header so I can google for the code some day and see who all is using it -- just for fun.

Thanks, Tim Dixon.

    /*  A better DateDiff Javascript Function.
        Written by Tim Dixon on 4 JUL 2007.
        No warranty. */
        
    function dateDiff(interval, date1, date2) {
        var divisor = 1;
        
        switch (interval) {
            case "day":
                divisor *= 24;
            case "hour":
                divisor *= 60;
            case "minute":
                divisor *= 60;
            case "second":
                divisor *= 1000;
                break;
            default:
                alert("Error in DateDiff(). Time interval '" + interval + "' not supported.\nOnly 'day', 'hour', 'minute' or 'second' are valid intervals.");
                return;
        }

        var ms1 = getMilliseconds(date1)
        var ms2 = getMilliseconds(date2)

        return ((ms2 - ms1) / divisor);
    }
    
    // Requires a four digit year "YYYY" other than that you can use pretty much any format you like.
    function getMilliseconds(date) {
        var ms = 0;
        
        date = date.toLowerCase();
        var bce = date.search(/bce|bc/);
        if (bce>-1) { 
            return -getMillisecondsBC(date.substring(0,bce));
        }

        var td = new Date(date);
         
        var start = date.search(/\d{4}/); // cheap fix.
        
        var year;
        if (start>-1) {
            year = parseInt(date.substring(start,start+4));
        }
        else {
            year = td.getFullYear();
        }
        
        var month = td.getMonth() + 1;
        var day = td.getDate();
        var hour = td.getHours();
        var minute = td.getMinutes();
        var second = td.getSeconds();
        var millisecond = td.getMilliseconds();
        var isLeap = isLeapYear(year)
        
        // Add years.
        for (i=1;i30) {
                    throw "'" + date + "' is not a valid date.";
                }               
                break;
            case 2:
                if ((isLeap==false)&(day>28)) {
                    throw "'" + date + "' is not a valid date.";
                }
                break;
            default: // 1,3,5,7,8,10,12
                if (day>31) {
                    throw "'" + date + "' is not a valid date.";
                }
        }

        ms+=(86400000*(day-1)); // Add days.
        ms+=(3600000*hour);     // Add hours.
        ms+=(60000*minute);     // Add minutes.
        ms+=(1000*second);      // Add seconds.
        ms+=millisecond;        // Add milliseconds.

        return ms;
    }
    
    function isLeapYear(year) {
        var retVal=false;
        if ((year % 4)==0) {
            if ((year % 100)==0) {
                if ((year % 400)==0) {
                    retVal=true;
                }
            }
            else {
                retVal=true;
            }
        }
        return retVal
    }
    
    // 1 B.C. = 0, 9 B.C. = 8, 101 B.C = 100, etc, according to the astronomical system and are all leap years.
    function isLeapYearBC(year) {
        var retVal=false;
        year-=1;
        if ((year % 4)==0) {
            if ((year % 100)==0) {
                if ((year % 400)==0) {
                    retVal=true;
                }
            }
            else {
                retVal=true;
            }
        }
        return retVal
    }
    
    function getDaysInMonthBC(year,month) {
        var retVal = 31;
        switch (month) {
            case 4: case 6: case 9: case 11:
                retVal = 30;
                break;
            case 2:
                if (isLeapYearBC(year)==true) {
                    retVal=29;
                }
                else {
                    retVal=28;
                }
        }
        return retVal;
    }
    
    function getMillisecondsBC(date) {
        var ms = 0;

        var td = new Date(date);

        var year;
        var start = date.search(/\d{4}/); // cheap fix.
        if (start>-1) {
            year = parseInt(date.substring(start,start+4));
        }
        else {
            year = td.getFullYear();
        }

        var month = td.getMonth() + 1;
        var day = td.getDate();
        var hour = td.getHours();
        var minute = td.getMinutes();
        var second = td.getSeconds();
        var millisecond = td.getMilliseconds();
        var isLeap = isLeapYearBC(year)
        
        // Add years.
        for (i=1;i30) {
                    throw "'" + date + "' is not a valid date.";
                }               
                break;
            case 2:
                if ((isLeap==false)&(day>28)) {
                    throw "'" + date + "' is not a valid date.";
                }
                break;
            default: // 1,3,5,7,8,10,12
                if (day>31) {
                    throw "'" + date + "' is not a valid date.";
                }
        }

        var daysInMonth = getDaysInMonthBC(year,month);

        ms-=(86400000*(day-1));     // Subtract days.
        ms-=(3600000*hour);         // Subtract hours.
        ms-=(60000*minute);         // Subtract minutes.
        ms-=(1000*second);          // Subtract seconds.
        ms-=millisecond;            // Subtract milliseconds.
        ms+=((daysInMonth+1)*86400000); // Add the days of the month. // added +1 may be incorrect calc

        return ms;
    }