130

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();
}
sg7
  • 6,108
  • 2
  • 32
  • 40
Chatu
  • 4,688
  • 3
  • 22
  • 15

21 Answers21

239

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

crg
  • 4,284
  • 2
  • 29
  • 57
FlySwat
  • 172,459
  • 74
  • 246
  • 311
  • 51
    this syntax has been confusing me for a while. To follow the JS pattern I'll recommend to implement the trick like this: `return new Date(year, month + 1, 0).getDate();` – fguillen Jul 24 '12 at 08:12
  • 2
    Unfortunately this fails for dates before 1000 AD where you can only set the year correctly by using SetFullYear(). To make it bullet proof use new Date( 2000+(year%2000), month, 0 ).getDate() – Noel Walters Feb 20 '13 at 14:55
  • 5
    Note to my future-self: fguillen's equation with the '+ 1' gives 28 days when the year is 2014 and the month is 1 (which, in JavaScript Date-object, means February). Probably want to go with that for least astonishment. But what a great idea from FlySwat! – Harry Pehkonen Feb 12 '14 at 14:43
  • @NoelWalters—you're correct that some browsers inocorrectly convert two digit years to dates in the 20th centry (so dates before 100 AD, not 1000 AD), however your fix doesn't rectify that in those browsers. The only way to reliably set two digit years is to use *setFullYear*: `var d=new Date();d.setFullYear(year, month, date);`. – RobG Apr 30 '14 at 23:08
  • 3
    What if `month` is **12**? Shouldn't the `Date` constructor take a value from **0 to 11**? – Snackoverflow Aug 15 '18 at 14:35
  • To get the [number of days in the current month](https://stackoverflow.com/a/69267613/7942242) – crg Sep 21 '21 at 10:53
  • 1
    but what about timezones? I tried this using a positive and negative timezone offset: with negative offset, this works, but the positive offset will return a day too few. – Ekkstein Mar 29 '22 at 10:10
11

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.

Community
  • 1
  • 1
GitaarLAB
  • 14,536
  • 11
  • 60
  • 80
  • This answer deserves more votes! It's the only one I saw that does not create a new Date object, which is a must if one is doing this multiple times. – Rodrigo Mar 22 '21 at 14:54
7

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();
    }
})();
Community
  • 1
  • 1
dolmen
  • 8,126
  • 5
  • 40
  • 42
  • 7
    Is the internal C/C++ routine so slow that this requires caching? – Pete Alvin May 01 '14 at 19:35
  • 1
    @PeteAlvin It depends on the implementation of `Date` (so there isn't an universal answer to that question) and how often your code will call the `dayInMonth` with the same values. So the only sensible answer is: profile your code and benchmark it! – dolmen May 03 '14 at 17:06
  • 1
    I like it! But instead of using a new object, `cache`, I use `localStorage`. – andrew Oct 29 '14 at 11:57
4

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
Jaybeecave
  • 827
  • 2
  • 8
  • 17
4

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
artem_p
  • 306
  • 2
  • 5
3

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.

Tomas Langkaas
  • 4,551
  • 2
  • 19
  • 34
  • I like that this answer doesnt use Date but making it a one liner make its really hard to actually follow is actually going on without further explanation – PhantomSpooks Jun 22 '22 at 19:38
2

Here is goes

new Date(2019,2,0).getDate(); //28
new Date(2020,2,0).getDate(); //29
Masum Billah
  • 2,209
  • 21
  • 20
2

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

Syed
  • 15,657
  • 13
  • 120
  • 154
2

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
RASG
  • 5,988
  • 4
  • 26
  • 47
  • 1
    When adding a new answer to an older question with 14 existing answers it is really important to note what new aspect of the question your answer addresses. Is it just the ES6 syntax? – Jason Aller Jun 15 '20 at 03:01
  • got it. will add context to the answer from now on. – RASG Jun 16 '20 at 17:09
1
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
        }
Tony Li
  • 116
  • 3
1

Considering leap years:

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];
}
Yash
  • 2,153
  • 2
  • 16
  • 11
  • Nice. Easy to look at. Prop[ertie]s for the use of an Inline-Map / Immediately-Keyed Value. – Cody Jun 04 '20 at 21:25
1

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!
mrplants
  • 657
  • 2
  • 9
  • 20
1

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;
}
ADyson
  • 57,178
  • 14
  • 51
  • 63
Shl
  • 3,130
  • 1
  • 17
  • 16
1

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;
},
kmiklas
  • 13,085
  • 22
  • 67
  • 103
1

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);
Sanka Sanjeewa
  • 1,993
  • 14
  • 16
1

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
Greg Herbowicz
  • 1,210
  • 1
  • 17
  • 18
1

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)
crg
  • 4,284
  • 2
  • 29
  • 57
1

You can get days in month by this command:

new Date(year, month, 0).getDate();
Mehran
  • 31
  • 5
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community May 09 '22 at 02:46
  • 1
    This answer has already been posted – MrCodingB May 12 '22 at 16:06
1

Try this - it returns dictionary with month: days mapping, I think it will be very useful in most cases when people enter this topic:

const getMonthsDaysForYear = (year) => {
  let monthDaysDictionary = {};

  for(let i = 1; i <= 11; i++) {
      const date = new Date(year, i + 1, 0);
      const monthName = date.toLocaleString('en-GB', { month: 'long' });
      monthDaysDictionary[monthName] = date.getDate();
  }

  return monthDaysDictionary;
}
getMonthsDaysForYear(2022);

Note: that month should be started with 1 as it is mentioned in this answer.

Mykyta Halchenko
  • 720
  • 1
  • 3
  • 21
0

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);
} 
0

@Tomas Langkaas : I've implemented essentially the same function you've mentioned above in awk, with some minor improvements :

  1. using conventional arithmetic instead of bit-wise AND ( & ), plus not using implementation-dependent features, making it fully POSIX-awk-complaint and portable (tested and confirmed working on mawk, gawk, and nawk)

2. user can now directly input actual month numbers of 1 - 12 instead of having to remember to pre-adjust them to 0 - 11

  1. instead of relying on hard-coded numerics, every constant, offset, modulo base etc now dynamically generated on the fly by the function itself ,

    while simultaneously being extremely temp variables efficient by recycling both the input month and year variables the moment their original values are no longer required, thus

  2. when February is being called without a year-value, it defaults to NOT-being a leap year, regardless of what the present year is

    {m,g,n}awk '
    
    function _____(_,__) {
        #
        #  _| Month  mm: [1-12]
        # __|  Year yyyy:
        #   |--->  #-days:
        #          in yyyy:mm: combo
        return -(\
        _^(_<_) != --_ \
            ? (_ %((_+=_+=_^=_<_) +--_)) %--_\
            : (_+=_^=_<_) + (__ == "" ||
              __ % (_+=_)         ||
          __% (_*(_*=_++)+_) == ! (__ % (_*_))\
              ) )  \
            -(_^=_<_) -+- ++_^_^_*_ 
    }'
    
    
                    2 1600   29
           2 1700 28
           2 1800 28
     2 1868   29
           2 1900 28
     2 1912   29
     2 1956   29
                    2 2000   29
     2 2012   29
     2 2016   29
     2 2018 28
     2 2020   29
     2 2022 28
     2 2024   29
    
RARE Kpop Manifesto
  • 2,453
  • 3
  • 11