Search code examples
javascripthtmldatetimeprototypejstimezone-offset

Date calculation - Daylight saving time (DST) and Timezone issue - Turkey


Date calculation issue in JavaScript on Browser. There are 3 parameters - From Date, No. of days & To Date

From Date selected using calendar component in JavaScript = 30/10/2016 No. of days entered = 2

Based on no. of days entered "To Date" should be calculated, so as per above input of From date & No. of days calculated "To Date" value should be 01/11/2016 but due to some wrong calculation it's showing 31/10/2016.

Time Zone - Istanbul, Turkey

Please refer below image for code snipped -

As it is clear from code snipped that prototype JavaScript library being used.

 dateUtil.prototype.addDays=function(date,noofDays)
{
	var _dateData=date.split("/");
	var _date=eval(_dateData[0]);
	var _month=eval(_dateData[1]);
	var _year=eval(_dateData[2]);
	var newFormatedDate = new Date(""+_month+"/"+_date+"/"+_year);
        var newAddedDate=newFormatedDate.getTime() + noofDays*24*60*60*1000; 
        var theDate = new Date(newAddedDate);
        var dd = theDate.getDate();
        var mm = theDate.getMonth()+1; // 0 based
        if(mm<10)
            mm="0"+mm;
        var yy = theDate.getYear();
        if (yy < 1000)
        yy +=1900; // Y2K fix
        var addedDate=""+dd+"/"+mm+"/"+yy;
        
	return addedDate;
} 

enter image description here

It seems noofDays*24*60*60*1000 logic is problem where DST is not being considered. There are 2 timezone showing with the same code but with different date format.

Please could you advise any guidance or read-up on this.

Edit : JavaScript code added.


Solution

  • Probably not worth posting the code since it has some fundamental errors that should not have survived the new millennium.

    var _date = eval(_dateDate[0]);
    

    Don't use eval. There are a small number of cases where it is appropriate, but in general, just don't use it. Ever. The above is the same as:

    var _date = _dateDate[0];
    

    Then there is:

    var newFormatedDate = new Date('' + _month + '/' + _date + '/' + _year)
    

    You started on the right track by avoiding parsing strings with the Date constructor by splitting the date string into it's parts. But then you undid that good work by creating a new string and parsing it with Date. Just use parts directly:

    var newFormatedDate = new Date(_year, _month-1, _date)
    

    which removes all the vagaries of Date parsing and is less to type as well. Also, Date objects don't have a format, so a name like date is fine.

    To add n days, just add them to the date:

    var date = new Date(_year, _month-1, _date)
    date.setDate(date.getDate() + 2); 
    

    So your function can be:

    function dateUtil(){}
    
    /* Add days to a date
    ** @param {string} date - date string in dd/mm/yyyy format
    ** @param {number} noofDays - number of days to add
    ** @returns {Date}
    */
    dateUtil.prototype.addDays = function(date, noofDays) {
      var dateData = date.split('/');
      var date = new Date(dateData[2], dateData[1] - 1, dateData[0]);
      date.setDate(date.getDate() + +noofDays);
      return date;
    }
    
    var d = new dateUtil();
    
    console.log(d.addDays('23/09/2016',3).toLocaleString());

    I've use +noofDays to ensure it's a number. Also, the SO console seems to always write dates as ISO 8601 strings in Z time zone so I've used toLocaleString to keep it in the host time zone.