0

I've an HTML5 datepicker, which value I want to change on button click.

<input type="date" id="datepicker" />
<button onclick="nextDay()">next</button>

My approach since the value is a string, is to parse it to Date, and after operating, convert it back to string. But my problem is, the Date's month, is from 0 to 11, whilst the datepicker's months are from 1 to 12.

The code:

// get the value
function getDatepicker() {
    // get
    var string = datepicker.val();

    var date;
    // verify the string is a valid date
    if (isNaN(Date.parse(string))) {
        // invalid date, get today()
        date = new Date();
    } else {
        // String to Date
        date = new Date(string);
    }
    return date;
}

// operate
function addDays(date, days) {
    date.setDate( new Date(date.getDate() + days));
    return date;
}

// set the value
function setDatepicker(date) {
    function addZero(num) {
        return ('0' + num).slice(-2);
    }
    date.setMonth( date.getMonth() +1 );

    var day = date.getDate();
    var month = date.getMonth();
    var year = date.getFullYear();

    var string = [year, addZero(month), addZero(day)].join('-');
    datepicker.val(string);
}

var date = getDatepicker();
addDays(date,-1);
setDatepicker(date);

Apparently since the datepicker initial value is right, when converting to Date, it does it correctly, but when converting the Date to datepicker value it substracts one month. It works fine from day to day, but fails when changing the month, for example:

start date = 1/4/2017 -1day = 31/3/2017 +1month = 1/5/2017

And then the next time I get the datepicker value, will be 1/5/2017 -1month, and I'll be in an infinite loop.

Can someone please shed some light on how to fix that? Thanks in advance!

PS: tl;dr in bold :)

Dane411
  • 823
  • 1
  • 13
  • 27

4 Answers4

1

To parse a date as UTC, append a Z - e.g.: new Date('2017-01-05T10:20:30Z').

for set/get value of input: You sholud use [elem].value

function getDatepicker(value) {
    if (isNaN(Date.parse(value))) {
        return new Date();
    } else {
        return new Date(value+"T10:20:30Z");
    }
}
function addDays(value, date, days) {
    var date = getDatepicker(value);
    date.setDate( new Date(date.getDate() + days));
    return date;
}
function setDatepicker(date) {
    function addZero(num) {
        return ('0' + num).slice(-2);
    }
    date.setMonth( date.getMonth() +1 );
    var day = date.getDate();
    var month = date.getMonth();
    var year = date.getFullYear();
    var string = [year, addZero(month), addZero(day)].join('-');
    datepicker.value = string;
}
var datepicker = document.getElementById("datepicker");
document.getElementById("next").addEventListener("click", function(){
    //console.log(datepicker.value);
    var date = addDays(datepicker.value, date, 1);
    setDatepicker(date);
});
<input type="date" id="datepicker" />
<button id="next">next</button>
alessandrio
  • 4,282
  • 2
  • 29
  • 40
0

When I update the datepicker in updateDatepickerById, I add 1 to the month like so: var month = date.getMonth() + 1;.

var GetDateFromDatepickerById = function (id) {
  var datepicker = document.getElementById(id);
  var date = new Date(datepicker.value);
  date = addDay(date, 1);
  return date;
};

var addDay = function (date, days) {
  date.setDate(date.getDate() + days);
  return date;
};

var updateDatepickerById = function (id, date) {
  var datepicker = document.getElementById(id);

  var year = date.getFullYear();
  var month = date.getMonth() + 1;
  month = month > 9 ? month.toString() : "0" + month;
  var day = date.getDate();
  day = day > 9 ? day.toString() : "0" + day;

  datepicker.value = year + "-" + month + "-" + day;
};

var nextDay = function () {
  var date = GetDateFromDatepickerById("datepicker");
  date = addDay(date, 1);
  updateDatepickerById("datepicker", date);
};
christo8989
  • 6,442
  • 5
  • 37
  • 43
0

here's my approach :

<!doctype html>
<html>
<head>
    <meta charset = "utf-8">
    <script>
  document.addEventListener("DOMContentLoaded", function(event) { // as per https://developer.mozilla.org/fr/docs/Web/Events/DOMContentLoaded

    console.log("DOM fully loaded and parsed");

    Date.prototype.toDateInputValue = (function() { // as per http://stackoverflow.com/questions/6982692/html5-input-type-date-default-value-to-today
        var local = new Date(this);
        local.setMinutes(this.getMinutes() - this.getTimezoneOffset());
        return local.toJSON().slice(0,10);
    }); 


    /* set the date to toDay for test purposes */
    document.getElementById('datePicker').value = new Date().toDateInputValue();

    /* get the date as string */
    formDate = document.getElementById('datePicker').value;
    console.log(formDate);

    //make it a Date object:    
    newDat = new Date(formDate);

    // add/substract x days
    var x = (-33); //for example
    dayValue = newDat.getUTCDate();

    // https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Date/setDate
    newDat.setDate(dayValue + x);
    console.log("new date : " +  newDat); // -> the date is correct

    //set the input with it :
    var day = newDat.getUTCDate();
    var month = newDat.getMonth() + 1; // this method indeed returns 0 to 11 (!) so you need to add 1
    var year = newDat.getFullYear();

    //make the new date a string
    newStrDat = year + '-' + ('0' + month).slice(-2) + '-' + ('0' + day).slice(-2);
    console.log(newStrDat);

    //set the field with it :-)
    document.getElementById('datePicker').value = newStrDat;


  });

  </script>

</head>
<body>
    <div>
        <input id = "datePicker" type = "date">

    </div>

   </body>
<html>
St3an
  • 726
  • 1
  • 6
  • 21
0

Since the other answers didn't seem to fix my problem, finally I went for moment.js as @christo8989 suggested.

// get the value
function getDatepicker() {
    return datepicker.value;
}

// operate
function addDays(date, days) {
    return moment(date).add(days, 'days').format('YYYY-MM-DD');
}

// set the value
function setDatepicker(date) {
    datepicker.value = date;
}

Much simpler than my approach! Thanks! :)

Dane411
  • 823
  • 1
  • 13
  • 27