Reputation: 4788
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();
}
Upvotes: 138
Views: 41022
Reputation: 2915
@Tomas Langkaas : I've implemented essentially the same function you've mentioned above in awk
, with some minor improvements :
&
), 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
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
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
Upvotes: 0
Reputation: 798
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.
Upvotes: 1
Reputation: 4731
//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");
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.
Upvotes: 5
Reputation: 1
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);
}
Upvotes: 0
Reputation: 41
You can get days in month by this command:
new Date(year, month, 0).getDate();
Upvotes: 2
Reputation: 4577
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)
Upvotes: 1
Reputation: 886
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
Upvotes: 5
Reputation: 175733
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
Upvotes: 247
Reputation: 1238
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
Upvotes: 1
Reputation: 6242
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
Upvotes: 3
Reputation: 3560
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);
Upvotes: 2
Reputation: 16543
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
Upvotes: 2
Reputation: 2409
Here is goes
new Date(2019,2,0).getDate(); //28
new Date(2020,2,0).getDate(); //29
Upvotes: 3
Reputation: 13453
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;
},
Upvotes: 1
Reputation: 3688
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;
}
Upvotes: 1
Reputation: 677
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!
Upvotes: 1
Reputation: 14655
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.
Upvotes: 13
Reputation: 316
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
Upvotes: 4
Reputation: 2183
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];
}
Upvotes: 1
Reputation: 116
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
}
Upvotes: 1
Reputation: 8706
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();
}
})();
Upvotes: 7