Calculate last day of month in JavaScript

Calculate last day of month in JavaScript

If you provide 0 as the dayValue in Date.setFullYear you get the last day of the previous month:
d = new Date(); d.setFullYear(2008, 11, 0); // Sun Nov 30 2008

There is reference to this behaviour at mozilla. Is this a reliable cross-browser feature or should I look at alternative methods?

Solutions/Answers:

Solution 1:

var month = 0; // January
var d = new Date(2008, month + 1, 0);
alert(d); // last day in January

IE 6: Thu Jan 31 00:00:00 CST 2008
IE 7: Thu Jan 31 00:00:00 CST 2008
IE 8: Beta 2: Thu Jan 31 00:00:00 CST 2008
Opera 8.54: Thu, 31 Jan 2008 00:00:00 GMT-0600
Opera 9.27: Thu, 31 Jan 2008 00:00:00 GMT-0600
Opera 9.60: Thu Jan 31 2008 00:00:00 GMT-0600
Firefox 2.0.0.17: Thu Jan 31 2008 00:00:00 GMT-0600 (Canada Central Standard Time)
Firefox 3.0.3: Thu Jan 31 2008 00:00:00 GMT-0600 (Canada Central Standard Time)
Google Chrome 0.2.149.30: Thu Jan 31 2008 00:00:00 GMT-0600 (Canada Central Standard Time)
Safari for Windows 3.1.2: Thu Jan 31 2008 00:00:00 GMT-0600 (Canada Central Standard Time)

Output differences are due to differences in the toString() implementation, not because the dates are different.

Related:  Canvas signature touch creates issue in phonegap

Of course, just because the browsers identified above use 0 as the last day of the previous month does not mean they will continue to do so, or that browsers not listed will do so, but it lends credibility to the belief that it should work the same way in every browser.

Solution 2:

I would use an intermediate date with the first day of the next month, and return the date from the previous day:

int_d = new Date(2008, 11+1,1);
d = new Date(int_d - 1);

Solution 3:

I find this to be the best solution for me. Let the Date object calculate it for you.

var today = new Date();
var lastDayOfMonth = new Date(today.getFullYear(), today.getMonth()+1, 0);

Setting day parameter to 0 means one day less than first day of the month which is last day of the previous month.

Solution 4:

In computer terms, new Date() and regular expression solutions are slow! If you want a super-fast (and super-cryptic) one-liner, try this one (assuming m is in Jan=1 format). I keep trying different code changes to get the best performance.

Related:  How Can I Truncate A String In jQuery?

My current fastest version:

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

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

Given the bit-shifting this obviously assumes that your m & y parameters are both integers, as passing numbers as strings would result in weird results.

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 than (5546>>m&1) on almost all browsers.

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


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

A quick lesson in binary months:

Related:  how to upload and delete files from dropzone.js

If you interpret the index of the desired months (Jan = 1) in binary you will notice that months with 31 days either have bit 3 clear and bit 0 set, or bit 3 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 the value 3 places with >> 3, XOR the bits with the original ^ m and see if the result is 1 or in bit position 0 using & 1. Note: It turns out + is slightly faster than XOR (^) and (m >> 3) + m gives the same result in bit 0.

JSPerf results: http://jsperf.com/days-in-month-perf-test/6

Solution 5:

My colleague stumbled upon the following which may be an easier solution

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

stolen from http://snippets.dzone.com/posts/show/2099

Solution 6:

A slight modification to solution provided by lebreeze:

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