JavaScript ile bir aydaki gün sayısını belirlemenin en iyi yolu nedir?


107

Bu işlevi kullanıyorum, ancak bunu elde etmenin en verimli ve doğru yolunun ne olduğunu bilmek istiyorum.

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

Yanıtlar:


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. Gün, önceki ayın son günüdür. Ay yapıcısı 0 tabanlı olduğundan, bu iyi çalışıyor. Biraz hack, ama temelde 32 çıkararak yaptığınız şey bu.


42
bu sözdizimi bir süredir kafamı karıştırıyor. JS kalıbını takip etmek için hile şu şekilde uygulanmasını tavsiye edeceğim:return new Date(year, month + 1, 0).getDate();
fguillen

2
Ne yazık ki bu, MS 1000'den önceki tarihler için başarısız olur, burada yılı yalnızca SetFullYear () kullanarak doğru şekilde ayarlayabilirsiniz. Kurşun geçirmez hale getirmek için yeni Tarih (2000+ (% 2000 yılı), ay, 0) .getDate ()
Noel Walters

4
Gelecekteki benliğime not: fguillen'in '+ 1' denklemi, yıl 2014 ve ay 1 olduğunda 28 gün verir (JavaScript Date nesnesinde Şubat anlamına gelir). Muhtemelen en az şaşkınlık için bununla gitmek istiyor. Ama FlySwat'den ne harika bir fikir!
Harry Pehkonen

@ NoelWalters — bazı tarayıcıların yanlış bir şekilde iki basamaklı yılları 20. yüzyıldaki tarihlere dönüştürdüğünü (yani MS 1000'den önce değil, MS 100'den önceki tarihler) doğru söylüyorsunuz, ancak sizin düzeltmeniz bu tarayıcılarda bunu düzeltmiyor. İki basamaklı yılları güvenilir bir şekilde ayarlamanın tek yolu setFullYear : kullanmaktır var d=new Date();d.setFullYear(year, month, date);.
RobG

1
Ne olursa montholduğunu 12 ? Kurucunun 0 ile 11Date arasında bir değer alması gerekmez mi?
anddero

8

Bu işlevi sık sık çağırırsanız, daha iyi performans için değeri önbelleğe almak yararlı olabilir.

FlySwat'ın cevabının önbelleğe alınmış versiyonu :

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
Dahili C / C ++ rutini, önbelleğe alma gerektirecek kadar yavaş mı?
Pete Alvin

1
@PeteAlvin Bu, uygulamasına Date(yani bu sorunun evrensel bir cevabı yoktur) ve kodunuzun hangi sıklıkla dayInMonthaynı değerlerle çağrılacağına bağlıdır . Yani tek mantıklı cevap: kodunuzun profilini çıkarın ve kıyaslayın!
dolmen

1
Bunu sevdim! Ama yeni bir nesne kullanmak yerine cachekullanıyorum localStorage.
Andrew

5

Bazı cevaplar (diğer sorular için de) artık yıl problemlerine sahipti veya Date nesnesini kullandı. Javascript'in Date object1 Ocak 1970'in her iki tarafında yaklaşık 285616 yılı (100.000.000 gün) kapsamasına rağmen , farklı tarayıcılarda (özellikle 0'dan 99'a kadar) her türlü beklenmedik tarih tutarsızlığından bıkmıştım . Nasıl hesaplayacağımı da merak ediyordum.

Bir basit ve her şeyden yazdığı Yani, küçük algoritma hesaplamak için doğru ( ilerisini düşünerek Gregoryen / Astronomik / ISO 8601: 2004 (madde 4.3.2.1), bu yüzden yıl0 var ve artık yıl olup negatif yıl desteklenir ) günün için sayısını belirli bir ay ve yıl.
Bu kullanan kısa devre bit maskesi-modülo leapYear algoritması (biraz js için modifiye edilmiş) ve ortak mod-8 aylık algoritması.

O Not AD/BCgösterimde, yıl 0 AD / BC yok: yerine yıl 1 BCsıçrama yıllık olduğunu!
BC notasyonunu hesaba katmanız gerekiyorsa, önce (aksi takdirde pozitif) yıl değerinden bir yıl çıkarın !! (Veya 1sonraki yıl hesaplamaları için yılı 'den çıkarın .)

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>

Ayların 1 temelli olması gerektiğini unutmayın!

Dikkat edin, bu farklı bir algoritmadır ve Javascript'imde kullandığım sihirli sayı araması yılın günü (1-366) cevabını hesaplar , çünkü burada artık yıl için fazladan dal sadece Şubat için gereklidir.


4

Karışıklığı gidermek için muhtemelen şu anda 1 tabanlı olduğu için ay dizesini temel alırdım.

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 ile daysInMonth () yöntemini kullanabilirsiniz:

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

2

İşte gidiyor

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

2

ES6 sözdizimi

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

İadeler

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

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

1
Mevcut 14 cevabı olan eski bir soruya yeni bir cevap eklerken, cevabınızın hangi yeni yönünü ele aldığına dikkat etmek gerçekten önemlidir. Yalnızca ES6 sözdizimi mi?
Jason Aller

anladım. bundan sonra yanıta bağlam katacak.
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

Artık yıllara bakıldığında:

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

Güzel. Bakması kolay. Satır İçi Harita / Anında Anahtarlanmış Değer kullanımı için özellikler.
Cody

1

Tek satırlık doğrudan hesaplama (Date nesnesi yok):

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 tabanlı aylarla varyasyon:

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

Bir Date nesnesinin geçerli ayındaki gün sayısını istiyorsanız, aşağıdaki yöntemi göz önünde bulundurun:

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

O zaman şu şekilde çalıştırabilirsiniz:

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

Tek satırda:

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

Seçilen cevapla karşılaştırıldığında biraz fazla öldürme olabilir :) Ama işte burada:

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

Yukarıdaki kodu burada buldum: 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));

Yukarıdaki kodu burada buldum: https://github.com/datejs/Datejs/blob/master/src/core.js


1

Bir tarih değişkeni geçirecekseniz bu yardımcı olabilir

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

daysInThisMonth = getDaysInMonth(new Date());

console.log(daysInThisMonth);


-1

Belki de en zarif çözüm değil, ancak anlaşılması ve bakımı kolay; ve savaşta test edilmiştir.

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;
},
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.