JavaScriptで1か月の日数を決定する最良の方法は何ですか?


107

私はこの関数を使用してきましたが、それを取得するための最も効率的で正確な方法を知りたいのですが。

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

回答:


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日目は前月の最終日です。月コンストラクタは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
私のフューチャーセルフに注意してください。「+ 1」を使用したfguillenの方程式は、年が2014年で月が1の場合に28日になります(JavaScriptのDateオブジェクトでは2月を意味します)。たぶん、少なくとも驚きにはそれを使いたいと思うでしょう。しかし、FlySwatからの素晴らしいアイデアは何でしょうか。
ハリーペコネン2014

@NoelWalters-一部のブラウザは2桁の年を20世紀の日付に誤って変換する(つまり、西暦100年より前の日付で、西暦1000年ではない)ことは正しいですが、修正によってこれらのブラウザではそれが修正されません。2桁の年を確実に設定する唯一の方法は、setFullYear:を使用することですvar d=new Date();d.setFullYear(year, month, date);
RobG 2014

1
12の場合monthはどうなりますか?コンストラクターは0から11までの値を取るべきではありませんか?Date
anddero 2018

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 ++ルーチンが遅いので、キャッシュが必要ですか?
ピートアルヴィン2014年

1
@PeteAlvinそれはDate(その質問に対する普遍的な答えはありません)の実装と、コードがdayInMonth同じ値でを呼び出す頻度に依存します。したがって、唯一の賢明な答えは、コードをプロファイルしてベンチマークすることです。
ドルメン

1
私はそれが好きです!しかし、新しいオブジェクトを使用する代わりにcache、を使用しますlocalStorage
アンドリュー、2014年

5

一部の回答(他の質問についても)には、うるう年の問題があるか、Dateオブジェクトが使用されていました。Date object1970年1月1日のどちらの側でも、javascript は約285616年(1億日)をカバーしますが、さまざまなブラウザー(特に0から99年)全体で、あらゆる種類の予期しない日付の不一致にうんざりしていました。計算方法にも興味がありました。

だから私は正しいProleptic Gregorian / Astronomical / ISO 8601:2004(clause 4.3.2.1))を計算するためのシンプルで何よりも小さなアルゴリズムを書いたので、が存在し、うるう年であり、負の年がサポートされています)の日数特定の月と年。 これは、使用短絡ビットマスク-モジュロleapYearアルゴリズム(わずかにJSのために修正された)と共通MOD-8月アルゴリズム。 0

AD/BC表記では、0年のAD / BCは存在しないことに注意してください。代わりに、年1 BCはうるう年です。
BC表記を考慮する必要がある場合は、最初に(そうでなければ正の)年の値から1年を引いてください!! (または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)の回答を計算するのとは異なります。うるう年の追加のブランチが必要なのは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

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構文だけですか?
Jason Aller

とった。これから答えにコンテキストを追加します。
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

うるう年を考える:

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

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;
},
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.