用JavaScript确定一个月中的天数的最佳方法是什么?


107

我一直在使用此功能,但我想知道什么是最有效,最准确的方法。

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

Answers:


200

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.

第0天是上个月的最后一天。由于month构造函数基于0,因此效果很好。有点骇客,但这基本上就是您减去32的结果。


42
这种语法使我困惑了一段时间。为了遵循JS模式,我建议实施以下技巧:return new Date(year, month + 1, 0).getDate();
fguillen

2
不幸的是,这对于公元1000年之前的日期失败,在该日期您只能使用SetFullYear()正确设置年份。要使其具有防弹功能,请使用新的Date(2000+(year%2000),month,0).getDate()
Noel Walters

4
请注意我的未来自我:fguillen的方程式中带有“ +1”的年份为2014,月份为1(在JavaScript日期对象中为2月),给出28天。可能想为此而感到惊讶。但是FlySwat的一个好主意!
哈里·佩科宁2014年

@NoelWalters-您正确的说,某些浏览器错误地将两位数字年份转换为20世纪的日期(因此日期转换为100 AD之前的日期,而不是1000 AD),但是您的修正不能在这些浏览器中更正此错误。可靠设置两位数年的唯一方法是使用调用setFullYearvar d=new Date();d.setFullYear(year, month, date);
RobG

1
如果month12Date构造函数不应该采用0到11之间的值吗?
anddero '18

8

如果您经常调用此函数,则缓存该值以提高性能可能会很有用。

这是FlySwat的答案的缓存版本:

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

6
内部C / C ++例程是否太慢以至于需要缓存?
皮特·阿尔文

1
@PeteAlvin这取决于的实现Date(因此,该问题没有一个统一的答案)以及您的代码多久dayInMonth使用一次相同的值进行调用。因此,唯一明智的答案是:分析您的代码并对其进行基准测试!
2014年

1
我喜欢!但是cache,我使用而不是使用新对象localStorage
andrew 2014年

5

有些答案(也有其他问题)有leap年问题或使用了Date对象。尽管javascript Date object在1970年1月1日的任一边涵盖了大约285616年(100,000,000天),但我对不同浏览器中各种意外的日期不一致感到厌烦(最著名的是0到99年)。我也很好奇如何计算。

所以我写了一个简单而重要的是,的算法计算出正确的Proleptic 公历 /天文/ ISO 8601:2004(第4.3.2.1),那么一年0存在且是一个闰年和消极年支持)当天对数给定的月份和年份。
它使用短路位掩码模moduloYearYear算法(对js稍作修改)和常见的mod-8 month算法。

请注意,在AD/BC符号中,不存在AD / BC 0年:相反,year 1 BC是the年!
如果您需要考虑BC表示法,则只需先减去一年(否则为正数)年值即可!!(或从中减去年份以1进行进一步的年度计算。)

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>

请注意,月份必须基于1!

请注意,这是与我在Javascript中使用的幻数查询算法计算一年中的一天(1-366)答案不同的算法,因为这里because年的额外分支只需要2月。


4

为了消除混乱,我可能将基于月份的字符串作为当前的基于1的字符串。

function daysInMonth(month,year) {
    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

4

使用moment.js,您可以使用daysInMonth()方法:

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

2

这是去

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

2

ES6语法

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

退货

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

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

1
在为现有问题有14个的较旧问题添加新答案时,一定要特别注意您的答案要解决的问题的新方面。仅仅是ES6语法吗?
杰森·艾勒

得到它了。从现在开始将上下文添加到答案中。
RASG

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
        }

1

考虑leap年:

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];
}

真好 容易看。使用内联映射/立即键值的属性。
科迪

1

单线直接计算(无Date对象):

function daysInMonth(m, y) {//m is 1-based, feb = 2
   return 31 - (--m ^ 1? m % 7 & 1:  y & 3? 3: y % 25? 2: y & 15? 3: 2);
}

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

从0开始的月份的变化:

function daysInMonth(m, y) {//m is 0-based, feb = 1
   return 31 - (m ^ 1? m % 7 & 1:  y & 3? 3: y % 25? 2: y & 15? 3: 2);
}

1

如果要获取Date对象在当前月份中的天数,请考虑以下方法:

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

然后,您可以像这样运行它:

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!

1

在一行中:

// 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;
}

1

与选定的答案相比,可能会造成致命的破坏:)但是,这是:

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

我在这里找到了上面的代码: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));

我在这里找到了上面的代码:https : //github.com/datejs/Datejs/blob/master/src/core.js


1

如果您要传递日期变量,这可能会有所帮助

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

daysInThisMonth = getDaysInMonth(new Date());

console.log(daysInThisMonth);


-1

也许不是最优雅的解决方案,但易于理解和维护;并且,它经过了战斗考验。

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;
},
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.