What is the best way to determine the number of days in a month with JavaScript?

Posted on

What is the best way to determine the number of days in a month with JavaScript? – Even if we have a good project plan and a logical concept, we will spend the majority of our time correcting errors abaout javascript and date. Furthermore, our application can run without obvious errors with JavaScript, we must use various ways to ensure that everything is operating properly. In general, there are two types of errors that you’ll encounter while doing something wrong in code: Syntax Errors and Logic Errors. To make bug fixing easier, every JavaScript error is captured with a full stack trace and the specific line of source code marked. To assist you in resolving the JavaScript error, look at the discuss below to fix problem about What is the best way to determine the number of days in a month with JavaScript?.

Problem :

I’ve been using this function but I’d like to know what’s the most efficient and accurate way to get it.

function daysInMonth(iMonth, iYear) {
   return 32 - new Date(iYear, iMonth, 32).getDate();
}

Solution :

function daysInMonth (month, year) { // Use 1 for January, 2 for February, etc.
  return new Date(year, month, 0).getDate();
}

console.log(daysInMonth(2, 1999)); // February in a non-leap year.
console.log(daysInMonth(2, 2000)); // February in a leap year.

Day 0 is the last day in the previous month. Because the month constructor is 0-based, this works nicely. A bit of a hack, but that’s basically what you’re doing by subtracting 32.

See more :
Number of days in the current month

Some answers (also on other questions) had leap-year problems or used the Date-object. Although javascript’s Date object covers approximately 285616 years (100,000,000 days) on either side of January 1 1970, I was fed up with all kinds of unexpected date inconsistencies across different browsers (most notably year 0 to 99). I was also curious how to calculate it.

So I wrote a simple and above all, small algorithm to calculate the correct (Proleptic Gregorian / Astronomical / ISO 8601:2004 (clause 4.3.2.1), so year 0 exists and is a leap year and negative years are supported) number of day’s for a given month and year.
It uses the short-circuit bitmask-modulo leapYear algorithm (slightly modified for js) and common mod-8 month algorithm.

Note that in AD/BC notation, year 0 AD/BC does not exist: instead year 1 BC is the leap-year!
IF you need to account for BC notation then simply subtract one year of the (otherwise positive) year-value first!! (Or subtract the year from 1 for further year-calculations.)

function daysInMonth(m, y){
  return m===2?y&3||!(y%25)&&y&15?28:29:30+(m+(m>>3)&1);
}
<!-- example for the snippet -->
<input type="text" value="enter year" onblur="
  for( var r='', i=0, y=+this.value
     ; 12>i++
     ; r+= 'Month: ' + i + ' has ' + daysInMonth(i, y) + ' days<br>'
     );
  this.nextSibling.innerHTML=r;
" /><div></div>

Note, months must be 1-based!

Note, this is a different algorithm then the magic number lookup I used in my Javascript calculate the day of the year (1 – 366) answer, because here the extra branch for the leap-year is only needed for February.

If you call this function often, it may be useful to cache the value for better performance.

Here is caching version of FlySwat’s answer:

var daysInMonth = (function() {
    var cache = {};
    return function(month, year) {
        var entry = year + '-' + month;

        if (cache[entry]) return cache[entry];

        return cache[entry] = new Date(year, month, 0).getDate();
    }
})();

With moment.js you can use daysInMonth() method:

moment().daysInMonth(); // number of days in the current month
moment("2012-02", "YYYY-MM").daysInMonth() // 29
moment("2012-01", "YYYY-MM").daysInMonth() // 31

To take away confusion I would probably make the month string based as it is currently 0 based.

function daysInMonth(month,year) {
    var monthNum =  new Date(Date.parse(month +" 1,"+year)).getMonth()+1
    return new Date(year, monthNum, 0).getDate();
}

daysInMonth('feb', 2015)
//28

daysInMonth('feb', 2008)
//29

One-liner direct computation (no Date object):

//m is 0-based, Jan = 0, Dec = 11

function daysInMonth(m,y){
   return 31-(m-1?m%7&1:y&(y%25?3:15)?3:2);
}

console.log(daysInMonth(1, 2003), "days in February in the non-leap year 2003");
console.log(daysInMonth(1, 2004), "days in February in the leap year 2004");
console.log(daysInMonth(1, 2100), "days in February in the non-leap year 2100");
console.log(daysInMonth(1, 2000), "days in February in the leap year 2000");

console.log(daysInMonth(0, 2022), "days in January 2022");
console.log(daysInMonth(1, 2022), "days in February 2022");
console.log(daysInMonth(2, 2022), "days in March 2022");
console.log(daysInMonth(3, 2022), "days in April 2022");
console.log(daysInMonth(4, 2022), "days in May 2022");
console.log(daysInMonth(5, 2022), "days in June 2022");
console.log(daysInMonth(6, 2022), "days in July 2022");
console.log(daysInMonth(7, 2022), "days in August 2022");
console.log(daysInMonth(8, 2022), "days in September 2022");
console.log(daysInMonth(9, 2022), "days in October 2022");
console.log(daysInMonth(10, 2022), "days in November 2022");
console.log(daysInMonth(11, 2022), "days in December 2022");

Explanation

The main idea is to assume that months have 31 days, but subtract 1 if the month is April, June, September, or November; subtract 2 if the month is February in a leap year; or subtract 3 if the month is February in a non-leap year.

In the ternary expression (m - 1 ? /* Not February */ : /* February */), the expression m - 1 checks whether the month is February.

For other months than February, the expression m % 7 makes m even for months with 31 days, and odd for the rest. Subtracting the lowest bit (& 1) results in 31 − 1 days for April, June, September, and November, and 31 − 0 days for the rest.

For February, the expression y & (y % 25 ? 3 : 15) is falsy for leap years, resulting in 31 − 2 days in February. Otherwise, February is 31 − 3 days.

Here is goes

new Date(2019,2,0).getDate(); //28
new Date(2020,2,0).getDate(); //29

May be bit over kill when compared to selected answer 🙂 But here it is:

function getDayCountOfMonth(year, month) {
  if (month === 3 || month === 5 || month === 8 || month === 10) {
    return 30;
  }

  if (month === 1) {
    if (year % 4 === 0 && year % 100 !== 0 || year % 400 === 0) {
      return 29;
    } else {
      return 28;
    }
  }

  return 31;
};

console.log(getDayCountOfMonth(2020, 1));

I found the above code over here: https://github.com/ElemeFE/element/blob/dev/src/utils/date-util.js

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

const getDaysInMonth = function (year, month) {
  return [31, (isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
};

console.log(getDaysInMonth(2020, 1));

I found the above code over here: https://github.com/datejs/Datejs/blob/master/src/core.js

ES6 syntax

const d = (y, m) => new Date(y, m, 0).getDate();

returns

console.log( d(2020, 2) );
// 29

console.log( d(2020, 6) );
// 30

function numberOfDays(iMonth, iYear) {
         var myDate = new Date(iYear, iMonth + 1, 1);  //find the fist day of next month
         var newDate = new Date(myDate - 1);  //find the last day
            return newDate.getDate();         //return # of days in this month
        }

function (year, month) {
    var isLeapYear = ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0);

    return [31, (isLeapYear ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
}

If you want the number of days in the current month of a Date object, consider the following method:

Date.prototype.getNumberOfDaysInMonth = function(monthOffset) {
    if (monthOffset !== undefined) {
        return new Date(this.getFullYear(), this.getMonth()+monthOffset, 0).getDate();
    } else {
        return new Date(this.getFullYear(), this.getMonth(), 0).getDate();
    }
}

Then you can run it like this:

var myDate = new Date();
myDate.getNumberOfDaysInMonth(); // Returns 28, 29, 30, 31, etc. as necessary
myDate.getNumberOfDaysInMonth(); // BONUS: This also tells you the number of days in past/future months!

In a single line:

// month is 1-12
function getDaysInMonth(year, month){
    return month == 2 ? 28 + (year % 4 == 0 ? (year % 100 == 0 ? (year % 400 == 0 ? 1 : 0) : 1):0) : 31 - (month - 1) % 7 % 2;
}

Perhaps not the most elegant solution, but easy to understand and maintain; and, it’s battle-tested.

function daysInMonth(month, year) {
    var days;
    switch (month) {
        case 1: // Feb, our problem child
            var leapYear = ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
            days = leapYear ? 29 : 28;
            break;
        case 3: case 5: case 8: case 10: 
            days = 30;
            break;
        default: 
            days = 31;
        }
    return days;
},

If you are going to pass a date variable this may helpful

const getDaysInMonth = date =>
  new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();

daysInThisMonth = getDaysInMonth(new Date());

console.log(daysInThisMonth);

One-liner, without using Date objects:

const countDays = (month, year) => 30 + (month === 2 ? (year % 4 === 0 && 1) - 2 : (month + Number(month > 7)) % 2);

returns:

countDays(11,2020) // 30
countDays(2,2020) // 29
countDays(2,2021) // 28

To get the number of days in the current month

var nbOfDaysInCurrentMonth = new Date(Date.UTC(new Date().getUTCFullYear(), new Date().getUTCMonth(), 0)).getDate()

console.log(nbOfDaysInCurrentMonth)

You can get days in month by this command:

new Date(year, month, 0).getDate();

See my function and a test of it:

function numberOfDays(year, month)
{
// Reference:
// https://arslankuyumculuk.com/how-to-calculate-leap-year-formula/ (2022-05-20 16:45 UTC)

numDays=0;
switch(month)
{
    case 1:
        numDays=31;
        break;
    case 2:
        numDays=28;
        break;
    case 3:
        numDays=31;
        break;
    case 4:
        numDays=30;
        break;
    case 5:
        numDays=31;
        break;
    case 6:
        numDays=30;
        break;
    case 7:
        numDays=31;
        break;
    case 8:
        numDays=31;
        break;
    case 9:
        numDays=30;
        break;
    case 10:
        numDays=31;
        break;
    case 11:
        numDays=30;
        break;
    case 12:
        numDays=31;
        break;
}

if(month==2)
{
    if( (year % 100) == 0 )
    {
        if( (year % 400) == 0 )
        {
            numDays=29;
        }
    }
    else
    {
        if( (year % 4) == 0 )
        {
            numDays=29;
        }
    }
}

//
return numDays;

}

// Test:

const years = [2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2100,2400];
month=2;
for (let i = 0; i < years.length; i++) 
{
    let text = "";
    text += years[i] + '/' + month.toString() + ": " + numberOfDays(years[i], month).toString();
    alert(text);
} 

for (let m = 1; m <= 12; m++) 
{
    let text2 = "";
    text2 += "2022/" + m.toString() + ": " + numberOfDays(2022, m).toString();
    alert(text2);
} 

Leave a Reply

Your email address will not be published. Required fields are marked *