6

I tried searching for the solution in existing stackoverflow answers but I was not finding a suitable answer...

I have 3fields..

  • Year select
  • Month select
  • Date select

If you select the leap year means, February month date will change to 29 days.. But that still shows the 28 days.. Don't know what problem in my code.

var numDays = {
        '1': 31, '2': 28, '3': 31, '4': 30, '5': 31, '6': 30,
        '7': 31, '8': 31, '9': 30, '10': 31, '11': 30, '12': 31
    };

    function setDays(oMonthSel, oDaysSel, oYearSel)
    {
        var nDays, oDaysSelLgth, opt, i = 1;
        nDays = numDays[oMonthSel[oMonthSel.selectedIndex].value];
        if (nDays == 28 && oYearSel[oYearSel.selectedIndex].value % 4 == 0)
            ++nDays;
        oDaysSelLgth = oDaysSel.length;
        if (nDays != oDaysSelLgth)
        {
            if (nDays < oDaysSelLgth)
                oDaysSel.length = nDays;
            else
                for (i; i < nDays - oDaysSelLgth + 1; i++)
                {
                    opt = new Option(oDaysSelLgth + i, oDaysSelLgth + i);
                    oDaysSel.options[oDaysSel.length] = opt;
                }
        }
        var oForm = oMonthSel.form;
        var month = oMonthSel.options[oMonthSel.selectedIndex].value;
        var day = oDaysSel.options[oDaysSel.selectedIndex].value;
        var year = oYearSel.options[oYearSel.selectedIndex].value;
        oForm.dob.value = month + '/' + day + '/' + year;
    }
    var min = new Date().getFullYear(),
            max = min - 13,
            select = document.getElementById('year');
    for (var i = (min - 100); i <= max; i++) {
        var opt = document.createElement('option');
        opt.value = i;
        opt.innerHTML = i;
        select.appendChild(opt);
    }
    date = document.getElementById('day');
    for (var i = 1; i <= 31; i++) {
        var opt = document.createElement('option');
        opt.value = i;
        opt.innerHTML = i;
        date.appendChild(opt);
    }
    jQuery('.month_sel,.day_sel,.year_sel').selectpicker({
        size: 8
    });

<select class="year_sel common_sel" name="year" id="year" onchange="setDays(month, day, this)">
<option value="">Year</option>
</select>
<select name="month" id="month" onchange="setDays(this, day,year)" class="month_sel common_sel">
<option value="">Month</option>
<option value="1">January</option>
<option value="2">February</option>
<option value="3">March</option>
<option value="4">April</option>
<option value="5">May</option>
<option value="6">June</option>
<option value="7">July</option>
<option value="8">August</option>
<option value="9">September</option>
<option value="10">October</option>
<option value="11">November</option>
<option value="12">December</option>
</select>
<select class="day_sel common_sel" name="day" id="day" onchange="setDays(month, this, year)">
<option value="">Day</option>
</select>
<input type="hidden" name="dob" value="" />
Prasath V
  • 1,336
  • 4
  • 20
  • 39
  • Please provide a more complete example... – rpadovani Aug 09 '16 at 10:33
  • 1
    FWIW leap years are more complex than just `% 4` - if it's divisable by 100 then it _isn't_ a leap year, unless it's divisible by 400, in which case it _is_. 2000 was a fun time for many reasons, not just the infamous "Y2K bug" :) – James Thorpe Aug 09 '16 at 10:33
  • This might help: http://stackoverflow.com/a/25588568/3783478 – Rajesh Aug 09 '16 at 10:37
  • Possible duplicate of [javascript to find leap year](http://stackoverflow.com/questions/8175521/javascript-to-find-leap-year) – Evan Trimboli Aug 09 '16 at 10:49
  • I note that everyone is concentrating on the leap year issue (which indeed is a problem), but at the end of the day your code should work - just for more years than it should. I think you need to post more context, like the contents of the year dropdown for instance. Do the values _actually_ properly correspond to the years etc? You need to create a [mcve] really. – James Thorpe Aug 09 '16 at 10:52
  • 1
    I will post the following codes.. – Prasath V Aug 09 '16 at 10:53
  • 1
    `var min = new Date().getFullYear(), max = min - 13, select = document.getElementById('year'); for (var i = (min - 100); i <= max; i++) { var opt = document.createElement('option'); opt.value = i; opt.innerHTML = i; select.appendChild(opt); }` **this part is for year** – Prasath V Aug 09 '16 at 10:55
  • 1
    **and last part** `date = document.getElementById('day'); for (var i = 1; i <= 31; i++) { var opt = document.createElement('option'); opt.value = i; opt.innerHTML = i; date.appendChild(opt); }` – Prasath V Aug 09 '16 at 10:56
  • Please [edit] all the relevant details into your question. – James Thorpe Aug 09 '16 at 11:05
  • Have you figured this out? You should pick an answer or let us know what's unresolved. – Whothehellisthat Aug 21 '16 at 08:30

5 Answers5

2

This bit is wrong:

if (nDays == 28 && oYearSel[oYearSel.selectedIndex].value % 4 == 0)
    ++nDays;

It's more complex than that. The rule is: If the year is evenly divisible by 4 and either it is not evenly divisible by 100 or it is evenly divisible by 400, it's a leap year.

So

if (nDays == 28) {
    var year = oYearSel[oYearSel.selectedIndex].value;
    if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) {
        nDays = 29;
    }
}

For instance, 2000 was a leap year; that was unusual, 75% of the time centuries aren't (1900 was not, nor will 2100 be).

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
2

You can just use JavaScript's built-in Date object. Just set it to 29th February for the given year. Then check if it was actually set to February (leap-year), or if it rolled on to March (not a leap-year).

var year = (new Date()).getFullYear();
new Date(year + "-02-29").getMonth() === 1;
Whothehellisthat
  • 2,072
  • 1
  • 14
  • 14
  • You can do the constructor in any way you like; the main thing is to let Date figure out the leap year for you ^^ – Whothehellisthat Aug 09 '16 at 10:48
  • I would not use the string format for the constructor though since date string parsing isn't guaranteed to be consistent http://dygraphs.com/date-formats.html. You should use new Date(year, 1, 29).getMonth(); – mcgraphix Aug 09 '16 at 13:55
2

You can use date object and compute final date of a month and process accordingly:

Sample

function getDaysInMonth(year, month){
  return new Date(year, month+1, 0).getDate();
}

console.log(getDaysInMonth(2016,1));
console.log(getDaysInMonth(2010,1));
console.log(getDaysInMonth(2000,1));
console.log(getDaysInMonth(2100,1));
Community
  • 1
  • 1
Rajesh
  • 24,354
  • 5
  • 48
  • 79
0

This will add a new method to the Date object:

    Date.prototype.isLeapYear = function() {
      if (0 == this.getFullYear() % 400) return true;
      if (0 == this.getFullYear() % 100) return false;
      return (0 == this.getFullYear() % 4) ? true : false;
    }

I've used this for years, it works!

Add the script some place in your code, then call it from the date you want to check:

    var dtTest = new Date();
    alert(dtTest + " Is leapyear = " + dtTest.isLeapYear());

or construct a date to test:

    var dtTest = new Date(2016,8,9);
    alert(dtTest + " Is leapyear = " + dtTest.isLeapYear());
SPlatten
  • 5,334
  • 11
  • 57
  • 128
0

Convert the year, month and day inputs to a JavaScript date and check the converted date matches your input:

const isValidDate = (year, month, day) => {
  const testDate = new Date(year, month, day);
  return
    testDate.getFullYear() === year &&
    testDate.getMonth() === month &&
    testDate.getDate() === day;
};

This assumes:

  • year, month and day inputs are numbers and not strings
  • month is zero indexed
Alasdair McLeay
  • 2,572
  • 4
  • 27
  • 50