Today, I will show you how you can generate an input field that will enable users to select a date using JavaScript.

Our Date Input will take note of **leap years** and **months** that have either 31 or 30 days.

This means that:

- if you select a leap year, and you choose the month of February, the days will count up to 29
- If you choose the month of January, the days will count up to 31.

## LET'S BEGIN

We will create a blank HTML file and add the Select fields; year, month, and day.

```
<!doctype html>
<html>
<head></head>
<body>
<select id="select_year" start="1900" end="2022">
</select>
<select id="select_month">
</select>
<select id="select_day">
</select>
</body>
</html>
```

We will leave the fields empty and use their respective IDs (Identifiers) to refer to them in JavaScript.

### Generate Days

In order to generate the days, we will start at the **index of 1** and increment the value to the maximum number of days in a calendar which is **31**, then create an option tag and set both the value and text to our current index.

### Generate Months

In order to generate the months, we will start at the **index of 1** and increment the value to the maximum number of months in a calendar which is **12**, then create an option tag and set both the value and text to our current index.

### Generate Years

If you take a close look at the **year Select Element**, you will see the attributes **start** and **end**.

These attributes will help us to generate the years from the specified start index to the end index.

```
document.addEventListener('DOMContentLoaded', function(){
const yearElem = document.querySelector('#select_year');
const dayElem = document.querySelector('#select_day');
const monthElem = document.querySelector('#select_month');
let days = 31; // maximum number of days
let months = 12; // maximum number of months
let yearStart = (yearElem.getAttribute("start")) ? yearElem.getAttribute("start") : 1900;
let yearEnd = (yearElem.getAttribute("end")) ? yearElem.getAttribute("end") : 2022;
let d = 1;
while(d <= days){
const opt = document.createElement("option");
opt.setAttribute("value", d);
opt.innerText = d;
dayElem.appendChild(opt);
++d;
}
let m = 1;
while(m <= months){
const opt = document.createElement("option");
opt.setAttribute("value", m);
opt.innerText = m;
monthElem.appendChild(opt);
++m;
}
while(yearStart <= yearEnd){
const opt = document.createElement("option");
opt.setAttribute("value", yearStart);
opt.innerText = yearStart;
yearElem.appendChild(opt);
++yearStart;
}
})
```

### Regenerate Days

Now we need a function that will enable us to regenerate the days based on the length specified.

This means that if we choose the month of **September (09)**, the days will be regenerated and will count up to **30** instead of **31** because there are 30 days in the month of September.

In other to achieve this, we will create an array inside our function, that will store the days from (1 - 31), then shorten the length of the array based on the length parameter specified.

```
function buildDays(length){
let daysArry = [];
let d = 1;
while(d <= 31){
daysArry.push(d);
++d;
}
//shorten the length
daysArry.length = ( daysArry.length - length );
//empty the days element
dayElem.innerHTML = '';
//loop through array, then create option tag and append to element
daysArry.forEach(d => {
const opt = document.createElement("option");
opt.setAttribute("value", d);
opt.innerText = d;
dayElem.appendChild(opt);
});
}
```

Now in other to make use of this function, we need to create another function that will check the month selected.

We will use a switch statement in this function, to check the month selected and set the length appropriately.

```
function checkMonth(month){
let len = 0;
//check month that has 30 days
switch(month){
//september
case "9" :
len = 1;
break;
//april
case "4" :
len = 1;
break;
//june
case "6" :
len = 1;
break;
//november
case "11" :
len = 1;
break;
default :
len = 0;
break;
}
//check if february is selected
if(month == 2){
checkLeapYear(yearElem.value);
}else{
buildDays(len);
}
}
```

For our last function, we need to check if the Year selected is a leap year.

Back in High School, my Math Teacher told me that if a year is

divisible by 4, this means that such a year is a leap year.

For example, if you divide 2020 by 4, you will get an Integer (505). This means that the year 2020 was a leap year. But if you divide the year 2022 by 4, you will get a float (505.5). This means that the year 2022 is not a leap year.

So in our function, we will check if our division is an integer or a float using a Regular Expression, then rebuild our days appropriately.

```
//check leap year
function checkLeapYear(year){
let v = (year / 4) * 1;
//check if the result is an integer or a float using regExp
if(/^[0-9]+$/.test(v)){
(monthValue == 2) ?
buildDays(2) //29 days
: '';
}else{
(monthValue == 2) ?
buildDays(3) //28 days
: '';
}
}
```

### Almost Done

Now we need to attach an Event Listener to our Month and Year select elements, in order to execute our functions based on the selected values.

We will also make sure of not executing the function twice when the same value is provided, by saving the value to a variable.

```
//Month Element Event Listener
var monthValue = 0
monthElem.addEventListener('click', function(){
if(monthValue !== this.value){
monthValue = this.value;
checkMonth(this.value); //run the check month function
}
});
//Year Element Event Listener
var yearValue = 0;
yearElem.addEventListener('click', function(){
yearValue = this.value;
checkLeapYear(this.value); //check for leap year
});
```

So if we should select a month, say **September**, the function will rebuild the days up to **30**. And if we select the leap year, say **2020**, the function will check if the month selected is February (2) and it will rebuild the days up to **29** because there're **29** days in the month of February on a leap year.

## Testing our script

Copy and paste this code in a blank HTML page and try to select a leap year + February, a month that has 30 days in it.

```
document.addEventListener('DOMContentLoaded', function(){
const yearElem = document.querySelector('#select_year');
const dayElem = document.querySelector('#select_day');
const monthElem = document.querySelector('#select_month');
let days = 31; // maximum number of days
let months = 12; // maximum number of months
let yearStart = (yearElem.getAttribute("start")) ? yearElem.getAttribute("start") : 1900;
let yearEnd = (yearElem.getAttribute("end")) ? yearElem.getAttribute("end") : 2022;
let d = 1;
while(d <= days){
const opt = document.createElement("option");
opt.setAttribute("value", d);
opt.innerText = d;
dayElem.appendChild(opt);
++d;
}
let m = 1;
while(m <= months){
const opt = document.createElement("option");
opt.setAttribute("value", m);
opt.innerText = m;
monthElem.appendChild(opt);
++m;
}
while(yearStart <= yearEnd){
const opt = document.createElement("option");
opt.setAttribute("value", yearStart);
opt.innerText = yearStart;
yearElem.appendChild(opt);
++yearStart;
}
//build days
function buildDays(length){
let daysArry = [];
let d = 1;
while(d <= 31){
daysArry.push(d);
++d;
}
//shorten the length
daysArry.length = ( daysArry.length - length );
//empty the days element
dayElem.innerHTML = '';
//loop through array, then create option tag and append to element
daysArry.forEach(d => {
const opt = document.createElement("option");
opt.setAttribute("value", d);
opt.innerText = d;
dayElem.appendChild(opt);
});
}
//check selected month
function checkMonth(month){
let len = 0;
//check month that has 30 days
switch(month){
//september
case "9" :
len = 1;
break;
//april
case "4" :
len = 1;
break;
//june
case "6" :
len = 1;
break;
//november
case "11" :
len = 1;
break;
default :
len = 0;
break;
}
//check if february is selected
if(month == 2){
checkLeapYear(yearElem.value);
}else{
buildDays(len);
}
}
//check leap year
function checkLeapYear(year){
let v = (year / 4) * 1;
//check if the result is an integer or a float using regExp
if(/^[0-9]+$/.test(v)){
(monthValue == 2) ?
buildDays(2) //29 days
: '';
}else{
(monthValue == 2) ?
buildDays(3) //28 days
: '';
}
}
//Month Element Event Listener
var monthValue = 0
monthElem.addEventListener('click', function(){
if(monthValue !== this.value){
monthValue = this.value;
checkMonth(this.value); //run the check month function
}
});
//Year Element Event Listener
var yearValue = 0;
yearElem.addEventListener('click', function(){
yearValue = this.value;
checkLeapYear(this.value); //check for leap year
});
})
```

### The Year 2020 (Leap Year) + Month of February

### Month of January

### Month of September

## An Important Note

Most centurial years ( a period of 100 years ) are not leap years, even though they are divisible by 4.

Years such as **1700, 1800, and 1900** are not leap years but they are **divisible by 4**.

So this doesn’t agree with the fact that any year divisible by 4 must be a leap year.

According to this wonderful article, I got to realize that if a year is a centurial year ( a period of 100 years ), and is **divisible by 4, it must also be divisible by 400** in order to qualify as a leap year.

Years **1700, 1800, 1900 are all divisible by 4** but are not divisible by 400, so they don’t qualify as leap years **but the year 2000 is divisible by 4 and is also divisible by 400**. This makes the year 2000 a leap year.

Let us update the function that checks for leap years. Here’s what we will do;

- First, we check if it is a centurial year ( a period of 100 years ).

If the year provided is divisible by 100 ( without a remainder ), then it is a centurial year.

Then we check if it is divisible by 400 and is also divisible by 4 ( without a remainder ), if it is, we return the boolean (true) which means that the year is a leap year.

- Second, we check if it is not a centurial year, but is divisible by 4.

If the year provided is divisible by 4 ( without a remainder ), we return the boolean (true) which means that the year is a leap year.

If none of the above is true, our function returns false, which means that the year provided is not a leap year.

```
function checkLeapYear(year){
let result = false;
//check for leap year
(function(){
//check for centurial year
if( (year % 100) == 0 ) {
//check if centurial year is a leap year
if( ((year % 400) == 0) && ((year % 4) == 0) ){
return ( result = true );
}
}else if( (year % 4) == 0){
//check if it is not a centurial year but is divisible by 4
return ( result = true );
}
return ( result = false );
})();
//check if the result is true ( leap year )
if(result){
(monthValue == 2) ?
buildDays(2) //29 days
: '';
}else{
(monthValue == 2) ?
buildDays(3) //28 days
: '';
}
}
```

All you have to do is to replace the function that checks for leap year with the function above, and the script will work 100% just fine.

You've reached the end of my article.

## EXTRA

I recently launched a JavaScript package that validates your HTML forms using validation rules, regular expressions and form input attributes.

I will appreciate if you spared a few seconds to check it out.

Thank You

Image credit: vecteezy.com

## Top comments (2)

Thanks for sharing

You're welcome Francis!

Thank you for engaging