[ACCEPTED]-Number of days in any month-date

Accepted answer
Score: 51
function getDaysInMonth(m, y) {
   return /8|3|5|10/.test(--m)?30:m==1?(!(y%4)&&y%100)||!(y%400)?29:28:31;
}

0

Score: 45

Try this:

function numberOfDays(year, month) {
    var d = new Date(year, month, 0);
    return d.getDate();
}

Because of leap years you need 1 to pass the year too.

Score: 27

Thirty days hath September,
April, June, and November;
All the rest have thirty-one,
Excepting February alone,
Which hath twenty-eight days clear,
And twenty-nine in each leap year.

<3 Wikipedia

0

Score: 13

Loved James' answer. Reformatted slightly 1 for those interested.

function getDaysInMonth(m, y)
{
    // months in JavaScript start at 0 so decrement by 1 e.g. 11 = Dec
    --m;

    // if month is Sept, Apr, Jun, Nov return 30 days
    if( /8|3|5|10/.test( m ) ) return 30;

    // if month is not Feb return 31 days
    if( m != 1 ) return 31;

    // To get this far month must be Feb ( 1 )
    // if the year is a leap year then Feb has 29 days
    if( ( y % 4 == 0 && y % 100 != 0 ) || y % 400 == 0 ) return 29;

    // Not a leap year. Feb has 28 days.
    return 28;
}

Fiddle here

Score: 8

Everyone knows that counting Chuck's knuckle 66 sandwich beats mere poetry any day of the 65 week month..

Chuck Norris&#39; Fist. Count the knucle&#39;s.

If you can't get that to compile 64 and run (like the poetry), then read on.


Without 63 regex and minus 2 modulo remainder operations, also 62 without leap-year problems or the Date-object.
Although 61 javascript's Date object covers approximately 285616 60 years (100,000,000 days) on either side 59 of January 1 1970, I was fed up with all 58 kinds of unexpected date inconsistencies across different 57 browsers (most notably year 0 to 99). I 56 was also curious how to calculate it.

So 55 I wrote a simple and above all, small algorithm 54 (easily beating James' answer) to calculate 53 the correct (Proleptic Gregorian / Astronomical / ISO 8601:2004 (clause 52 4.3.2.1), so year 0 exists and is a leap year 51 and negative years are supported) number of day's for a given month 50 and year.
It uses the short-circuit bitmask-modulo leapYear algorithm (slightly modified 49 for js) and common mod-8 month algorithm 48 (again modified to obtain the shortest path).

Note 47 that in AD/BC notation, year 0 AD/BC does not 46 exist: instead year 1 BC is the leap-year!
IF 45 you need to account for BC notation then 44 simply subtract one year of the (otherwise 43 positive) year-value first!! (Or subtract 42 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" placeholder="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 41 must be 1-based (as the question asked for)!

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


EDIT (-history):
I lifted my 36 modified mod8 month algo

return(m===2?y&3||!(y%25)&&y&15?28:29:30)+(m+(m>>3)&1);   //algo 1

to the ternary 35 and removed the now un-needed outer parenthesis 34 (good call, TrueBlueAussie):

return m===2?y&3||!(y%25)&&y&15?28:29:30+(m+(m>>3)&1);    //algo 2

After 33 severe testing this turned out to be the 32 fastest algo (thanks TrueBlueAussie for 31 the tests to which I chipped in for the 30 caching jsperf setup). We guess the reason 29 that this is faster then my (shorter and 28 seemingly faster) algo 3 (the magic number 27 bitwise lookup below), is that modern browsers 26 can probably pre-optimise the constant bitshift 25 in m>>3.

I figured.. well.. "and why again 24 didn't I just do?:"

return m===2?y&3||!(y%25)&&y&15?28:29:30+(5546>>m&1);     // algo 3

It uses a a 'magic 23 number' to do a simple bit-wise lookup of 22 offsets:

DNOSAJJMAMFJ* = Months (right to left)
CBA9876543210 = Month === bit position in hex (we never use pos 0: January is 1)
1010110101010 = offset from 30 = binary === 5546 decimal

13 bits is less than 31 bits, so we can 21 safely save another character on the bitshift 20 instead of >>> (as we don't need to force unsigned 19 32 bit).

That eliminates one memory-call 18 (var m), one addition and one precedence! (and 17 it's one char shorter)

One would think that: obviously 16 these 3 extra optimizations beat my first/second 15 algo (which as TrueBlueAussie commented, was 14 already the fastest)...
But as I already 13 mentioned, it turned out that this (algo 12 3) is not faster on modern browsers (I know, rather unexpected), we think 11 it is because the engine can no longer optimize 10 the bitshift.
I'll leave it here, maybe 9 one day it will be faster, who knows..

As it 8 turned out my algo 2 was the fastest after-all (except 7 TrueBlueAussie's full 2D array of-course, although 6 that takes quite some more memory and still 5 requires a fast algo to build it client-side), I 4 followed TrueBlueAussie's advice to revert 3 my answer to using my algo 2.

Still I had 2 a blast collaborating and am grateful for 1 the incentive to revisit my answer !

Score: 5

In computer terms, new Date() and regular expression solutions are slow! If 39 you want a super-fast (and super-cryptic) one-liner, try 38 this one (assuming m is in Jan=1 format as per 37 the question):

The only real competition 36 for speed is from @GitaarLab, so I have 35 created a head-to-head JSPerf for us to 34 test on: http://jsperf.com/days-in-month-head-to-head/5

I keep trying different code changes 33 to get the best performance.

Current version

After looking 32 at this related question Leap year check using bitwise operators (amazing speed) and discovering 31 what the 25 & 15 magic number represented, I 30 have come up with this optimized hybrid 29 of answers:

function getDaysInMonth(m, y) {
    return m===2 ? y & 3 || !(y % 25) && y & 15 ? 28 : 29 : 30 + (m +(m >> 3) & 1);
}

JSFiddle: http://jsfiddle.net/TrueBlueAussie/H89X3/22/

JSPerf results: http://jsperf.com/days-in-month-head-to-head/5

For some reason, (m+(m>>3)&1) is more efficient 28 than (5546>>m&1) on almost all browsers.


Previous Versions:

This one removed 27 a single ! test by reversing the values (slight 26 increase):

function getDaysInMonth(m, y) {
    return m === 2 ? (y % 4 || !(y % 100) && (y % 400)) ? 28 : 29 : 30 + (m + (m >> 3) & 1);
}

This one removed any the unnecessary 25 brackets:

function getDaysInMonth2(m, y) {
    return m === 2 ? !(y % 4 || !(y % 100) && (y % 400)) ? 29 : 28 : 30 + (m + (m >> 3) & 1);
}

This one was down to + being a tad 24 faster than XOR (^)

function getDaysInMonth(m, y) {
    return (m === 2) ? (!((y % 4) || (!(y % 100) && (y % 400))) ? 29 : 28) : 30 + ((m + (m >> 3)) & 1);
}

This was my original stab 23 at it:

function getDaysInMonth(m, y) {
    return m == 2 ? (!((y % 4) || (!(y % 100) && (y % 400))) ? 29 : 28) : (30 + ((m >> 3 ^ m) & 1));
}

It works based on my leap year answer 22 here: javascript to find leap year this answer here Leap year check using bitwise operators (amazing speed) as well as the 21 following binary logic.


A quick lesson in binary months:

If you interpret 20 the index of the desired months (Jan = 1) in binary you 19 will notice that months with 31 days either 18 have bit 3 clear and bit 0 set, or bit 3 17 set and bit 0 clear.

Jan = 1  = 0001 : 31 days
Feb = 2  = 0010
Mar = 3  = 0011 : 31 days
Apr = 4  = 0100
May = 5  = 0101 : 31 days
Jun = 6  = 0110
Jul = 7  = 0111 : 31 days
Aug = 8  = 1000 : 31 days
Sep = 9  = 1001
Oct = 10 = 1010 : 31 days
Nov = 11 = 1011
Dec = 12 = 1100 : 31 days

That means you can shift 16 the value 3 places with >> 3, XOR the bits with 15 the original ^ m and see if the result is 1 or 14 0 in bit position 0 using & 1. Note: It turns out + is slightly 13 faster than XOR (^) and (m >> 3) + m gives the same result 12 in bit 0.

JSPerf results: http://jsperf.com/days-in-month-perf-test/6 (23 times faster than the accepted 11 answer).


Update: I ran a comparison of the top two 10 answers + latest (@James, @Caleb & @GitaarLAB) against 9 this one to ensure they gave consistent 8 results and all 4 return the same values 7 for all months in all years from year 1 6 to year 4000: http://jsfiddle.net/TrueBlueAussie/8Lmpnpz4/6/. Year 0 is the same for all 5 except @Caleb.

Another update:

If absolute speed were the 4 only goal, and you do not mind wasting memory, then 3 storing the results for a given span of 2 years, in a 2-dimensional table is probably 1 the fastest possible way:

function DIM(m, y) { //TrueBlueAussie
    return m===2?(y%4||!(y%100)&&(y%400))?28:29:30+(m+(m>>3)&1);
}
array = new Array(4000);
for (var y = 1; y < 4000; y++){
    array[y] = [];
    for (var m = 1; m < 13; m++)
    {
        array[y][m] = DIM(m, y);
    }
}

// This just does a lookup into the primed table - wasteful, but fast
function getDaysInMonth2(m, y){
    return array[y][m];
}

JSPerf: http://jsperf.com/days-in-month-head-to-head/5

Score: 1

In the spirit of not doing your homework for you, I present a version in 11 POVRay (sorry, not JS) I did many years ago.

In 10 POVRay, there are no boolean variables. The method 9 I came up with was to create a polynomial 8 in 'm' which gave an answer > 0 for months 7 with 31 days and < 0 for months with 6 30 days.

#declare m0 = (m-0.5)*(m-1.5)*(m-2.5)*(m-3.5)*(m-4.5)*(m-5.5);
#declare m0 = m0*(m-6.5)*(m-8.5)*(m-9.5)*(m-10.5)*(m-11.5);
#if (m0 > 0)
  #declare maxdays = 31;
#else
  #declare maxdays = 30;
#end

The tricky part is to decide when 5 the year is a leap year. This is the full 4 test for leap years. Most people are aware 3 of the 4-year rule, and since 2000, some 2 know about the 100 and 400 year rules, there 1 is no 4000 year rule.

#declare LEAPYEAR = 2.0;
#if (mod(YEAR,4.0)=0)
  #declare LEAPYEAR = 1.0;
  #if (mod(YEAR,100.0)=0)
    #declare LEAPYEAR = 2.0;
  #end
  #if (mod(YEAR,400.0)=0
    #declare LEAPYEAR = 1.0;
  #end
#end
#if (MONTH = 2.0)
  #declare maxdays = maxdays - LEAPYEAR;
#end
#if (DAY > maxdays)
  #declare MONTH = MONTH + 1;
  #declare DAY = DAY - maxdays;
#end
#if (MONTH > 12)
  #declare YEAR = YEAR + 1;
  #declare MONTH = MONTH - 12;
#end
Score: 1

Loved James' answer as well as Bruno's explanation 12 of it. However, got annoyed at the overly 11 cryptic nature of the solution. So here 10 is the same solution but cleaned of any 9 unnecessary over encryption.

function getDaysInMonth(m, y) {
   return /4|6|9|11/.test(m)?30:m==2?(!(y%4)&&y%100)||!(y%400)?29:28:31;
}

Specifics:

  1. Seems there's 8 no need to decrease month - javascript has 7 nothing to do with it, since we only use 6 it for comparison, so I used the real month 5 numbers for clarity.

  2. Why write the number 4 of april, june, september and november out 3 of order? That's just confusing.

  3. *Optionally, we 2 can increase the month (++m) to get a version that 1 accepts (new Date()).getMonth() as input

Score: 1

I came across this question whilst playing 8 with a C/C++/C# hobby project. So, although this answer 7 may not be pertinent to the OP, the remainder 6 of the answers/comments seem to concern 5 JavaScript "golf"; which is a 4 bit of a black art due to the vagaries of 3 JS JIT, but fun nonetheless.

Standing on 2 the shoulders of GitaarLAB, TrueBlueAussie, et al, I 1 propose:

return m===2?y&3||!(y%25)&&y&15?28:29:30|(m+(m>>3));
Score: 0

try this:

function DaysinMonth(aDate)  {
    return aDate.setMonth(aDate.getMonth()+1, 0).getDate();
}    

0

Score: 0

Try this:

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

    if (month == 2)
        return (isLeap) ? 29 : 28;
    return 30 + (month % 2);
}

0

More Related questions