days between two dates

GerbenRienkGerbenRienk Posts: 705 ✭✭✭
Hi All,
For those of us who want to do calculations with dates, for example the
number of days between two dates, I made a javascript: see below.
If you want to read the explanation and/or want to download a sample CRF,
go to
http://www.trialdatasolutions.com/tds/howto/datediff.jsp
As you can see I borrowed heavily from Sander de Ridders
https://en.wikibooks.org/wiki/OpenClinica_User_Manual/AgeField , but I
added i18n-support.
Kind regards,
Gerben Rienk
---
First date item should have
in the right_item_text
and second the same, except "Date2" and in the outcome-item:

// for OC versions before
3.1.4, use jquery-1.3.2.min.js !

$.noConflict();
jQuery(document).ready(function($) {
var fieldDate1 = $("#Date1").parent().parent().find("input");
var fieldDate2 = $("#Date2").parent().parent().find("input");
var fieldDiff = $("#Diff").parent().parent().find("input");
function OCDateToJDate(OCDate){
//this function takes a date item in OpenClinica-notation
//and returns a date object
//The names of the months are compared with the array in the Calendar
utility
//located in /includes/new_cal/lang
var dateParts = OCDate.split("-");
var JDate = new Date();
JDate.setFullYear(dateParts[2]);
JDate.setMonth(Calendar._SMN.indexOf(dateParts[1]));
JDate.setDate(dateParts[0]);
return JDate;
}
function DiffInDays(OCDate1, OCDate2){
//calculate how many milliseconds are in a day
var msecPerDay = 1000 * 60 * 60 * 24;
//calculate millisecs for both dates
var milliSec1=OCDateToJDate(OCDate1).getTime();
var milliSec2=OCDateToJDate(OCDate2).getTime();
//take the difference
var interval =milliSec2 - milliSec1;
//calculate the days
var days = Math.floor(interval / msecPerDay );
if (isNaN(days)){
return 0;
}
else{
return days;
}
}
function calcDiff(){
//calculate the difference
var calculatedDifference = DiffInDays(fieldDate1.val(), fieldDate2.val());
//only write the difference if it's not already there
if (fieldDiff.val() != calculatedDifference){
fieldDiff.val(calculatedDifference);
fieldDiff.change();
}
};
fieldDate1.blur(function(){
calcDiff();
});
fieldDate2.blur(function(){
calcDiff();
});
fieldDiff.blur(function(){
calcDiff();
})
fieldDiff.focus(function(){
calcDiff();
})
$("#srl").click(function(){
calcDiff();
});
$("#srh").click(function(){
calcDiff();
});
})

Comments

  • tdpurnattdpurnat Posts: 126
    another great tool, thanks!
    tina
    ----------
    Tina D Dannemann Purnat, M.Sc., PMP, CCDM
    Skype tdpurnat | Office +49 89 38 03 89 67 | http://www.linkedin.com/in/tinadpurnat
    Why are my emails so terse? emailcharter.org
    2013/10/15 Gerben Rienk
    Hi All,
    For those of us who want to do calculations with dates, for example the
    number of days between two dates, I made a javascript: see below.
    If you want to read the explanation and/or want to download a sample CRF,
    go to
    http://www.trialdatasolutions.com/tds/howto/datediff.jsp
    As you can see I borrowed heavily from Sander de Ridders
    https://en.wikibooks.org/wiki/OpenClinica_User_Manual/AgeField , but I
    added i18n-support.
    Kind regards,
    Gerben Rienk
    ---
    First date item should have
    in the right_item_text
    and second the same, except "Date2" and in the outcome-item:

    // for OC versions before
    3.1.4, use jquery-1.3.2.min.js !

    $.noConflict();
    jQuery(document).ready(function($) {
    var fieldDate1 = $("#Date1").parent().parent().find("input");
    var fieldDate2 = $("#Date2").parent().parent().find("input");
    var fieldDiff = $("#Diff").parent().parent().find("input");
    function OCDateToJDate(OCDate){
    //this function takes a date item in OpenClinica-notation
    //and returns a date object
    //The names of the months are compared with the array in the Calendar
    utility
    //located in /includes/new_cal/lang
    var dateParts = OCDate.split("-");
    var JDate = new Date();
    JDate.setFullYear(dateParts[2]);
    JDate.setMonth(Calendar._SMN.indexOf(dateParts[1]));
    JDate.setDate(dateParts[0]);
    return JDate;
    }
    function DiffInDays(OCDate1, OCDate2){
    //calculate how many milliseconds are in a day
    var msecPerDay = 1000 * 60 * 60 * 24;
    //calculate millisecs for both dates
    var milliSec1=OCDateToJDate(OCDate1).getTime();
    var milliSec2=OCDateToJDate(OCDate2).getTime();
    //take the difference
    var interval =milliSec2 - milliSec1;
    //calculate the days
    var days = Math.floor(interval / msecPerDay );
    if (isNaN(days)){
    return 0;
    }
    else{
    return days;
    }
    }
    function calcDiff(){
    //calculate the difference
    var calculatedDifference = DiffInDays(fieldDate1.val(), fieldDate2.val());
    //only write the difference if it's not already there
    if (fieldDiff.val() != calculatedDifference){
    fieldDiff.val(calculatedDifference);
    fieldDiff.change();
    }
    };
    fieldDate1.blur(function(){
    calcDiff();
    });
    fieldDate2.blur(function(){
    calcDiff();
    });
    fieldDiff.blur(function(){
    calcDiff();
    })
    fieldDiff.focus(function(){
    calcDiff();
    })
    $("#srl").click(function(){
    calcDiff();
    });
    $("#srh").click(function(){
    calcDiff();
    });
    })
  • albertkalbertk Posts: 18
    Hi Gerben,

    I would like to point out an error in the Javascript function you have provided, in the function DiffInDays. When using milliseconds to calculate difference between dates, you will get calculation errors in areas where Daylight Savings Time occurs, which results in the loss of a day.

    For reference, Sunday, March 10, 2013 was DST this year.

    No problem from 8 Mar to 9 Mar (1 day).
    Rounding error from 9 Mar to 10 Mar because floor(23 hours) = 0 days.

    A quick fix would be to add a single hour’s worth of milliseconds to the following line.

    //take the difference
    var interval =milliSec2 - milliSec1 + (1000 * 60 * 60); //increments the hour by 1

    When we examine the 9 Mar to 10 Mar example, the actual time calculated is 23 hours due to DST (we lose an hour). If we examine 2 Nov to 3 Nov, we end up getting 25 hours due to DST ending (we gain an hour). What ends up happening is we have a fuzziness of +/- 1 hour, with a floored 23 hours becoming 0 days and a floored 25 hours becoming 1 day. which when using the floor function, results in that weird dropped day only for dates that pass DST but do not pass the end of DST. So by shifting the interval +1 hour, we get a fuzziness of 0-2 hours, meaning our minimum value would be 24 hours (still 1 day) and our maximum value would be 26 hours, which would also floor to a single day.

    Adding the single hour patches everything up even through multiple years because the DST eliminates itself over a 365-day period by adding and subtracting that hour.

    The other alternative would be to convert the DiffInDays function to use the built-in Date object.

    Regards,
    -Albert


    -----Original Message-----
    Sent: Tuesday, October 15, 2013 6:37 AM
    To: users@openclinica.org
    Subject: [Users] days between two dates

    Hi All,

    For those of us who want to do calculations with dates, for example the number of days between two dates, I made a javascript: see below.
    If you want to read the explanation and/or want to download a sample CRF, go to http://www.trialdatasolutions.com/tds/howto/datediff.jsp

    As you can see I borrowed heavily from Sander de Ridders https://en.wikibooks.org/wiki/OpenClinica_User_Manual/AgeField , but I added i18n-support.

    Kind regards,

    Gerben Rienk

    ---
    First date item should have
    in the right_item_text and second the same, except "Date2" and in the outcome-item:


    // for OC versions before 3.1.4, use jquery-1.3.2.min.js ! $.noConflict();
    jQuery(document).ready(function($) {
    var fieldDate1 = $("#Date1").parent().parent().find("input");
    var fieldDate2 = $("#Date2").parent().parent().find("input");
    var fieldDiff = $("#Diff").parent().parent().find("input");

    function OCDateToJDate(OCDate){
    //this function takes a date item in OpenClinica-notation //and returns a date object //The names of the months are compared with the array in the Calendar utility //located in /includes/new_cal/lang var dateParts = OCDate.split("-"); var JDate = new Date(); JDate.setFullYear(dateParts[2]); JDate.setMonth(Calendar._SMN.indexOf(dateParts[1]));
    JDate.setDate(dateParts[0]);
    return JDate;
    }

    function DiffInDays(OCDate1, OCDate2){
    //calculate how many milliseconds are in a day var msecPerDay = 1000 * 60 * 60 * 24; //calculate millisecs for both dates var milliSec1=OCDateToJDate(OCDate1).getTime();
    var milliSec2=OCDateToJDate(OCDate2).getTime();
    //take the difference
    var interval =milliSec2 - milliSec1;
    //calculate the days
    var days = Math.floor(interval / msecPerDay ); if (isNaN(days)){
    return 0;
    }
    else{
    return days;
    }
    }

    function calcDiff(){
    //calculate the difference
    var calculatedDifference = DiffInDays(fieldDate1.val(), fieldDate2.val()); //only write the difference if it's not already there if (fieldDiff.val() != calculatedDifference){
    fieldDiff.val(calculatedDifference);
    fieldDiff.change();
    }
    };
    fieldDate1.blur(function(){
    calcDiff();
    });
    fieldDate2.blur(function(){
    calcDiff();
    });
    fieldDiff.blur(function(){
    calcDiff();
    })
    fieldDiff.focus(function(){
    calcDiff();
    })
    $("#srl").click(function(){
    calcDiff();
    });
    $("#srh").click(function(){
    calcDiff();
    });
    })
  • GerbenRienkGerbenRienk Posts: 705 ✭✭✭
    Hello Albert,
    Great feedback: thank you. I hadn't thought of DST, I must confess.
    I changed the script from
    var days = Math.floor(interval / msecPerDay );
    to
    var days = Math.round(interval / msecPerDay );
    and now your example of 9 and 10 March are OK.
    Kind regards,
    Gerben Rienk
    > > Hi Gerben,
    > >
    > >
    > >
    > > I would like to point out an error in the Javascript function you have
    > > provided, in the function DiffInDays. When using milliseconds to calculate
    > > difference between dates, you will get calculation errors in areas where
    > > Daylight Savings Time occurs, which results in the loss of a day.
    > >
    > >
    > >
    > > For reference, Sunday, March 10, 2013 was DST this year.
    > >
    > >
    > >
    > > [cid:image002.jpg@01CEC988.10B3FF10]
    > >
    > > No problem from 8 Mar to 9 Mar (1 day).
    > >
    > > [cid:image004.jpg@01CEC988.10B3FF10]
    > >
    > > Rounding error from 9 Mar to 10 Mar because floor(23 hours) = 0 days.
    > >
    > >
    > >
    > > A quick fix would be to add a single hour's worth of milliseconds to the
    > > following line.
    > >
    > >
    > >
    > > //take the difference
    > >
    > > var interval =milliSec2 - milliSec1 + (1000 * 60 * 60); //increments the
    > > hour by 1
    > >
    > >
    > >
    > > When we examine the 9 Mar to 10 Mar example, the actual time calculated is
    > > 23 hours due to DST (we lose an hour). If we examine 2 Nov to 3 Nov, we
    > > end up getting 25 hours due to DST ending (we gain an hour). What ends up
    > > happening is we have a fuzziness of ± 1 hour, with a floored 23 hours
    > > becoming 0 days and a floored 25 hours becoming 1 day. which when using
    > > the floor function, results in that weird dropped day only for dates that
    > > pass DST but do not pass the end of DST. So by shifting the interval +1
    > > hour, we get a fuzziness of 0-2 hours, meaning our minimum value would be
    > > 24 hours (still 1 day) and our maximum value would be 26 hours, which
    > > would also floor to a single day.
    > >
    > >
    > >
    > > Adding the single hour patches everything up even through multiple years
    > > because the DST eliminates itself over a 365-day period by adding and
    > > subtracting that hour.
    > >
    > >
    > >
    > > The other alternative would be to convert the DiffInDays function to use
    > > the built-in Date object.
    > >
    > >
    > >
    > > Regards,
    > >
    > > -Albert
    > >
    > >
    > >
    > >
    > >
    > > -----Original Message-----
    > >
    > > On Behalf Of Gerben Rienk
    > > Sent: Tuesday, October 15, 2013 6:37 AM
    > > To: users@openclinica.org
    > > Subject: [Users] days between two dates
    > >
    > >
    > >
    > > Hi All,
    > >
    > >
    > >
    > > For those of us who want to do calculations with dates, for example the
    > > number of days between two dates, I made a javascript: see below.
    > >
    > > If you want to read the explanation and/or want to download a sample CRF,
    > > go to http://www.trialdatasolutions.com/tds/howto/datediff.jsp
    > >
    > >
    > >
    > > As you can see I borrowed heavily from Sander de Ridders
    > > https://en.wikibooks.org/wiki/OpenClinica_User_Manual/AgeField , but I
    > > added i18n-support.
    > >
    > >
    > >
    > > Kind regards,
    > >
    > >
    > >
    > > Gerben Rienk
    > >
    > >
    > >
    > > ---
    > >
    > > First date item should have
    in the right_item_text
    > > and second the same, except "Date2" and in the outcome-item:
    > >
    > >
    > >
    > >

    > >
    > > // for OC versions before
    > > 3.1.4, use jquery-1.3.2.min.js ! $.noConflict();
    > >
    > > jQuery(document).ready(function($) {
    > >
    > > var fieldDate1 = $("#Date1").parent().parent().find("input");
    > >
    > > var fieldDate2 = $("#Date2").parent().parent().find("input");
    > >
    > > var fieldDiff = $("#Diff").parent().parent().find("input");
    > >
    > >
    > >
    > > function OCDateToJDate(OCDate){
    > >
    > > //this function takes a date item in OpenClinica-notation //and returns a
    > > date object //The names of the months are compared with the array in the
    > > Calendar utility //located in /includes/new_cal/lang var dateParts =
    > > OCDate.split("-"); var JDate = new Date();
    > > JDate.setFullYear(dateParts[2]);
    > > JDate.setMonth(Calendar._SMN.indexOf(dateParts[1]));
    > >
    > > JDate.setDate(dateParts[0]);
    > >
    > > return JDate;
    > >
    > > }
    > >
    > >
    > >
    > > function DiffInDays(OCDate1, OCDate2){
    > >
    > > //calculate how many milliseconds are in a day var msecPerDay = 1000 * 60
    > > * 60 * 24; //calculate millisecs for both dates var
    > > milliSec1=OCDateToJDate(OCDate1).getTime();
    > >
    > > var milliSec2=OCDateToJDate(OCDate2).getTime();
    > >
    > > //take the difference
    > >
    > > var interval =milliSec2 - milliSec1;
    > >
    > > //calculate the days
    > >
    > > var days = Math.floor(interval / msecPerDay ); if (isNaN(days)){
    > >
    > > return 0;
    > >
    > > }
    > >
    > > else{
    > >
    > > return days;
    > >
    > > }
    > >
    > > }
    > >
    > >
    > >
    > > function calcDiff(){
    > >
    > > //calculate the difference
    > >
    > > var calculatedDifference = DiffInDays(fieldDate1.val(), fieldDate2.val());
    > > //only write the difference if it's not already there if
    > > (fieldDiff.val() != calculatedDifference){
    > >
    > > fieldDiff.val(calculatedDifference);
    > >
    > > fieldDiff.change();
    > >
    > > }
    > >
    > > };
    > >
    > > fieldDate1.blur(function(){
    > >
    > > calcDiff();
    > >
    > > });
    > >
    > > fieldDate2.blur(function(){
    > >
    > > calcDiff();
    > >
    > > });
    > >
    > > fieldDiff.blur(function(){
    > >
    > > calcDiff();
    > >
    > > })
    > >
    > > fieldDiff.focus(function(){
    > >
    > > calcDiff();
    > >
    > > })
    > >
    > > $("#srl").click(function(){
    > >
    > > calcDiff();
    > >
    > > });
    > >
    > > $("#srh").click(function(){
    > >
    > > calcDiff();
    > >
    > > });
    > >
    > > })
    > >
    > >
    > >
    > >
    > >
    > >
    > >
    > >
  • jguptajgupta Posts: 13
    Recently we had two customers who reported that when using the above code they saw that if the date had February, it was being treated as March. that is 2/14/2013 was treated as 3/14/2013, hence a difference of -13 instead of 15.
    2/14/2013 and 3/1/2013; difference in days = -13 (should be 15)
    1/27/2015 and 2/25/2015; difference in days = 57 (should be 29)
    I looked into this further and found out the problem is happening because of error in Javascript setMonth() function.

    Here is link that talks about it more:-
    http://stackoverflow.com/questions/21490366/setmonth1-gives-me-march

    I created a work around for this issue, by not fragmenting the Date into year, month and day. Instead changing the date string in such a way that it could directly be processed by getTime() method call.

    function OCDateToJDate(input){
    var input1 = input.split("-").join("/");
    var myDate = new Date(input1);
    return myDate;
    }

    Please change the below function call to the above one, if you are experiencing this issue too.
    function OCDateToJDate(OCDate){
    //this function takes a date item in OpenClinica-notation
    //and returns a date object
    //The names of the months are compared with the array in the Calendar utility //located in /includes/new_cal/lang
    var dateParts = OCDate.split("-"); var JDate = new Date();
    JDate.setFullYear(dateParts[2]);
    JDate.setMonth(Calendar._SMN.indexOf(dateParts[1]));
    JDate.setDate(dateParts[0]);
    return JDate;
    }

    Hope this helps. I tested it with some sample dates, the fix seems to work.
    regards,
    Jigyasa
  • GerbenRienkGerbenRienk Posts: 705 ✭✭✭
    Hi Jigyasa,
    Thank you for the feedback! Very much appreciated.
    Your fix works, but only for OpenClinica installations with English as the only language. If you have other i18n-properties files, such as Japanese or Spanish, (or Dutch in my case) then you can not use the quick-route to initiate a date.
    A safe way to do it is using for example 1-Jan-1900 as initial date, or any other date, as long as the month has 31 days. For those interested: on http://www.trialdatasolutions.com/tds/howto/datediff.jsp you can read a more detailed explanation and/or download the sample CRF.
    Kind regards,
    Gerben Rienk
Sign In or Register to comment.