Was ist der beste Weg, um die Anzahl der Tage in einem Monat mit JavaScript zu bestimmen?

107

Ich habe diese Funktion verwendet, möchte aber wissen, wie dies am effizientesten und genauesten funktioniert.

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

Antworten:

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.

Tag 0 ist der letzte Tag im Vormonat. Da der Monatskonstruktor auf 0 basiert, funktioniert dies gut. Ein bisschen hacken, aber genau das tun Sie, indem Sie 32 abziehen.

FlySwat
quelle
42
Diese Syntax hat mich eine Weile verwirrt. Um dem JS-Muster zu folgen, empfehle ich, den Trick wie folgt zu implementieren:return new Date(year, month + 1, 0).getDate();
fguillen
2
Leider schlägt dies bei Daten vor 1000 n. Chr. Fehl, bei denen Sie das Jahr nur mit SetFullYear () korrekt einstellen können. Verwenden Sie das neue Datum (2000+ (Jahr% 2000), Monat, 0) .getDate ()
Noel Walters
4
Anmerkung für mein zukünftiges Selbst: Die Gleichung von fguillen mit der '+ 1' gibt 28 Tage an, wenn das Jahr 2014 und der Monat 1 ist (was in JavaScript Date-object Februar bedeutet). Wahrscheinlich möchte ich damit zumindest Erstaunen gehen. Aber was für eine großartige Idee von FlySwat!
Harry Pehkonen
@ NoelWalters - Sie haben Recht, dass einige Browser zweistellige Jahre falsch in Daten im 20. Jahrhundert konvertieren (also Daten vor 100 n. Chr., Nicht 1000 n. Chr.). Ihr Fix korrigiert dies jedoch in diesen Browsern nicht. Die einzige Möglichkeit, zweistellige Jahre zuverlässig einzustellen, ist die Verwendung von setFullYear : var d=new Date();d.setFullYear(year, month, date);.
RobG
1
Was passiert , wenn monthist 12 ? Sollte der DateKonstruktor nicht einen Wert von 0 bis 11 annehmen ?
Anddero
8

Wenn Sie diese Funktion häufig aufrufen, kann es hilfreich sein, den Wert für eine bessere Leistung zwischenzuspeichern.

Hier ist die Caching-Version der Antwort von 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();
    }
})();
Dolmen
quelle
6
Ist die interne C / C ++ - Routine so langsam, dass dies ein Caching erfordert?
Pete Alvin
1
@PeteAlvin Es hängt von der Implementierung von ab Date(daher gibt es keine universelle Antwort auf diese Frage) und davon, wie oft Ihr Code die dayInMonthmit denselben Werten aufruft . Die einzig sinnvolle Antwort lautet also: Profilieren Sie Ihren Code und vergleichen Sie ihn!
Dolmen
1
Ich mag das! Aber anstatt ein neues Objekt zu verwenden cache, verwende ich localStorage.
Andrew
5

Einige Antworten (auch auf andere Fragen) hatten Schaltjahrprobleme oder verwendeten das Date-Objekt. Obwohl Javascript Date objectauf beiden Seiten des 1. Januar 1970 ungefähr 285616 Jahre (100.000.000 Tage) abdeckt, hatte ich genug von allen Arten unerwarteter Datumsinkonsistenzen in verschiedenen Browsern (insbesondere Jahr 0 bis 99). Ich war auch neugierig, wie man es berechnet.

Also habe ich einen einfachen und vor allem kleinen Algorithmus geschrieben, um die korrekte ( Proleptic Gregorian / Astronomical / ISO 8601: 2004 ( Abschnitt 4.3.2.1), also Jahr0 existiert und ist ein Schaltjahr und negative Jahre werden unterstützt ) Anzahl der Tage für einen bestimmten Monat und ein bestimmtes Jahr.
Es verwendet den Kurzschluss-Bitmasken-Modulo-Schaltjahr-Algorithmus (leicht modifiziert für js) und den üblichen Mod-8-Monats-Algorithmus.

Beachten Sie, dass in der AD/BCNotation das Jahr 0 AD / BC nicht existiert: Stattdessen 1 BCist das Jahr das Schaltjahr!
WENN Sie die BC-Notation berücksichtigen müssen, subtrahieren Sie einfach zuerst ein Jahr vom (ansonsten positiven) Jahreswert !! (Oder subtrahieren Sie das Jahr von 1für weitere Jahresberechnungen.)

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>

Beachten Sie, dass Monate 1-basiert sein müssen!

Beachten Sie, dass dies ein anderer Algorithmus ist als die Suche nach magischen Zahlen, die ich in meinem Javascript verwendet habe, um den Tag des Jahres (1 - 366) zu berechnen , da hier der zusätzliche Zweig für das Schaltjahr nur für Februar benötigt wird.

GitaarLAB
quelle
4

Um Verwirrung zu vermeiden, würde ich wahrscheinlich die Monatszeichenfolge basierend machen, da sie derzeit auf 1 basiert.

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
Jaybeecave
quelle
4

Mit moment.js können Sie die daysInMonth () -Methode verwenden:

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

Hier geht es

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

ES6-Syntax

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

kehrt zurück

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

console.log( d(2020, 6) );
// 30
RASG
quelle
1
Wenn Sie einer älteren Frage mit 14 vorhandenen Antworten eine neue Antwort hinzufügen, ist es sehr wichtig zu beachten, welchen neuen Aspekt der Frage Ihre Antwort anspricht. Ist es nur die ES6-Syntax?
Jason Aller
Ich habs. wird der Antwort von nun an Kontext hinzufügen.
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
        }
Tony Li
quelle
1

In Anbetracht der Schaltjahre:

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];
}
Yash
quelle
Nett. Einfach anzusehen. Eigenschaften für die Verwendung einer Inline-Map / eines sofort verschlüsselten Werts.
Cody
1

Einzeilige direkte Berechnung (kein Datumsobjekt):

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

Variation mit 0-basierten Monaten:

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);
}
Tomas Langkaas
quelle
1

Wenn Sie die Anzahl der Tage im aktuellen Monat eines Datumsobjekts angeben möchten, ziehen Sie die folgende Methode in Betracht:

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

Dann können Sie es so ausführen:

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!
Pflanzen
quelle
1

In einer einzigen Zeile:

// 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;
}
Shl
quelle
1

Kann im Vergleich zur ausgewählten Antwort etwas übertrieben sein :) Aber hier ist es:

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

Ich habe den obigen Code hier gefunden: 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));

Ich habe den obigen Code hier gefunden: https://github.com/datejs/Datejs/blob/master/src/core.js

Syed
quelle
1

Wenn Sie eine Datumsvariable übergeben, kann dies hilfreich sein

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

daysInThisMonth = getDaysInMonth(new Date());

console.log(daysInThisMonth);

Sanka Sanjeeva
quelle
-1

Vielleicht nicht die eleganteste Lösung, aber leicht zu verstehen und zu warten; und es ist kampferprobt.

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;
},
kmiklas
quelle