8

I have 2 fields input and output dates. On certain conditions I set the endDate to be 1 year ahead of start date.

<input type='date' id='endDate'>
$("#startDate").change(function(){
    var endDate = new Date($("#startDate").val());
    endDate.setMonth(endDate.getMonth() + 1);
    endDate.setFullYear(endDate.getFullYear() + 1);
    var myDay = ("0" + endDate.getDate()).slice(-2);
    var myMonth = ("0" + endDate.getMonth()).slice(-2);
    $("#endDate").val(endDate.getFullYear() + '-' + myMonth + '-' + myDay);
}

The issue when I set the start date to 2-29-2016 I got the following error:

The specified value "2017-02-29" does not conform to the required format, "yyyy-MM-dd".

I expected the Date() function to take care of it. Apparently, they don't. Is this a bug?

Is their anyway faster than adding a bunch of if statements?

Syntax_Error
  • 5,964
  • 15
  • 53
  • 73

3 Answers3

10

The specified value "2017-02-29" does not conform to the required format, "yyyy-MM-dd".

2017-02-29 is not a valid date. 29th feb of next year (2017) is not possible.

Only leap years have february Month of 29.

Try 2016-02-29 instead.

Is their anyway faster than adding a bunch of if statements?

No need to add bunch of if statements, you can use this answer

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

For answering your question, if you set the date explicitly like "2017-02-29" then it will throw an error.

Just make changes in the date object itself and apply that date object to the input by

  $("#endDate").val( endDate.toJSON().slice(0,10) );

Now it should take care of rolling over to next month.

Edit (based on TJ's comment)

Leap years occur every year that is evenly divisible by 4 except ones evenly divisible by 100 (which are not leap years), except ones evenly divisible by 400 (which are leap years).

Community
  • 1
  • 1
gurvinder372
  • 66,980
  • 10
  • 72
  • 94
  • 1
    Leap years occur every year that is evenly divisible by 4 *except* ones evenly divisible by 100 (which are not leap years), *except* ones evenly divisible by 400 (which *are* leap years). – T.J. Crowder Feb 16 '16 at 10:07
  • 1
    Yes I know that this is an issue of leap years. But my question is, shouldn't the Date() function take care of it? Or should I do it manually? – Syntax_Error Feb 16 '16 at 10:07
  • @Syntax_Error check the my updated post about how to set updated date to the input date. Let me know if this worked. – gurvinder372 Feb 16 '16 at 10:53
7

The real problem here is that you've used the value of getMonth without adding 1 to it. The value from getMonth starts at 0 (January), but month values in your yyyy-MM-dd format start with 1.

So:

var myMonth = ("0" + (endDate.getMonth() + 1)).slice(-2);
// Note -------------^------------------^^^^^

That's how you ended up with an invalid string, 2017-02-29, despite having used the Date object, which will indeed ensure it only gives you valid dates. The Date object contained the date March 29th, not February 29th.

However:

On certain conditions I set the endDate to be 1 year ahead of start date.

Your code doesn't do that. It adds a year and a month, not just a year:

endDate.setMonth(endDate.getMonth() + 1);       // <== Changing month
endDate.setFullYear(endDate.getFullYear() + 1);

If you only want to add a year, remove the first of those two lines. That, combined, with the correction to how you're using getMonth when forming the string, will reliably add a year to the date (with possible month rollover).

So:

$("#startDate").change(function(){
    var endDate = new Date($("#startDate").val());
    endDate.setFullYear(endDate.getFullYear() + 1);
    var myDay = ("0" + endDate.getDate()).slice(-2);
    var myMonth = ("0" + (endDate.getMonth() + 1)).slice(-2);
    $("#endDate").val(endDate.getFullYear() + '-' + myMonth + '-' + myDay);
});
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
0

I overcame this bug by adding

@DateTimeFormat(pattern = "yyyy-MM-dd")
senior
  • 2,196
  • 6
  • 36
  • 54