Berechnen Sie den letzten Tag des Monats in JavaScript


276

Wenn Sie 0als dayValuein Date.setFullYearangeben, erhalten Sie den letzten Tag des Vormonats:

d = new Date(); d.setFullYear(2008, 11, 0); //  Sun Nov 30 2008

Es gibt Hinweise auf dieses Verhalten bei Mozilla . Ist dies eine zuverlässige browserübergreifende Funktion oder sollte ich nach alternativen Methoden suchen?


Meinen Sie nicht den letzten Tag des angegebenen Monats? Es gibt 30 Tage im November und 31 Tage im Oktober.
Chris Serra

16
Monate sind in Javascript nullbasiert, also ist 11 Dezember
Greg

2
@TheCloudlessSky - versuchen Sie es in Ihrer Konsole ... (2008,11,0) ist der nullte Tag im Dezember und daher der letzte Tag im November
Ken

@ Ken - Ja - ich wusste nicht, dass es eine "0" gibt :) ... es war zu früh am Morgen.
TheCloudlessSky

Antworten:


423
var month = 0; // January
var d = new Date(2008, month + 1, 0);
alert(d); // last day in January

IE 6:                     Thu Jan 31 00:00:00 CST 2008
IE 7:                     Thu Jan 31 00:00:00 CST 2008
IE 8: Beta 2:             Thu Jan 31 00:00:00 CST 2008
Opera 8.54:               Thu, 31 Jan 2008 00:00:00 GMT-0600
Opera 9.27:               Thu, 31 Jan 2008 00:00:00 GMT-0600
Opera 9.60:               Thu Jan 31 2008 00:00:00 GMT-0600
Firefox 2.0.0.17:         Thu Jan 31 2008 00:00:00 GMT-0600 (Canada Central Standard Time)
Firefox 3.0.3:            Thu Jan 31 2008 00:00:00 GMT-0600 (Canada Central Standard Time)
Google Chrome 0.2.149.30: Thu Jan 31 2008 00:00:00 GMT-0600 (Canada Central Standard Time)
Safari for Windows 3.1.2: Thu Jan 31 2008 00:00:00 GMT-0600 (Canada Central Standard Time)

Ausgabedifferenzen sind auf Unterschiede in der toString()Implementierung zurückzuführen, nicht auf unterschiedliche Daten.

Nur weil die oben genannten Browser 0 als letzten Tag des Vormonats verwenden, bedeutet dies natürlich nicht, dass sie dies weiterhin tun oder dass nicht aufgelistete Browser dies tun, aber es verleiht der Überzeugung Glaubwürdigkeit, dass es funktionieren sollte in jedem Browser gleich.


19
Das scheint perfekt zu funktionieren. Was verwenden Sie aus Neugier, um das Javascript auf all diesen Engines auszuführen? Hast du alles eingerichtet oder irgendein Werkzeug?
Neonski

5
Sie können d.getDate () verwenden, um den tatsächlichen Tag abzurufen.
Rynop

35
"Nur weil die Browser ... 0 als letzten Tag des Vormonats verwenden, heißt das nicht, dass sie dies auch weiterhin tun werden." Ja, sie sind von ECMA-262 dazu verpflichtet.
RobG

3
Bitte beachten Sie, dass die Verwendung new Dateist so viel langsamer als andere Berechnungsmethoden , dass es nicht einmal auf dem perf Diagramm ist angezeigt : jsperf.com/days-in-month-perf-test/6
gegangenes Coding

4
Bei Chrome 48.0.2564.116 funktioniert das nicht. Vielleicht hat dieser Weg aufgehört, der "Standard" zu sein.
Xarlymg89

77

Ich würde ein Zwischendatum mit dem ersten Tag des nächsten Monats verwenden und das Datum vom vorherigen Tag zurückgeben:

int_d = new Date(2008, 11+1,1);
d = new Date(int_d - 1);

Gemäß der ECMAScript-Spezifikation ist die Verwendung des Konstruktors "Date" gültig, wie Sie bereits erwähnt haben. Nach dem von der Funktion "MakeDay" angegebenen Algorithmus sollte das Problem gut behandelt werden.
Pablo Cabrera

1
Dies ist die beste Lösung IMO. Ich habe die akzeptierte Antwort ausprobiert, aber es gibt einen Fehler beim Abrufen des letzten des aktuellen Monats. Es gibt das heutige Datum zurück. Ich bin mir nicht sicher, warum das passiert.
Gogol

1
Ich kann den Fehler nicht tadeln. Dies gibt mir das richtige Datum in allen Browsern:today = new Date(); new Date(today.getFullYear(), today.getMonth()+1, 0).toString();
Orad

Dadurch wird ein Datumsobjekt für den letzten Tag des Monats erstellt, dessen Uhrzeit auf die letzte Millisekunde eingestellt ist (dh 23: 59: 59.999). Verwenden Sie die Methode besser einfach im OP und speichern Sie den zusätzlichen Schritt und das Datumsobjekt.
RobG

@RobG: Ich stimme zu! Obwohl meine Lösung möglicherweise leichter zu verstehen ist, fühlt sich die Vorstellung, 0 für den letzten Tag des Monats zu verwenden, meiner Meinung nach etwas klobig an.
Karlipoppins

72

Ich finde das die beste Lösung für mich. Lassen Sie das Date-Objekt es für Sie berechnen.

var today = new Date();
var lastDayOfMonth = new Date(today.getFullYear(), today.getMonth()+1, 0);

Das Setzen des Tagesparameters auf 0 bedeutet einen Tag weniger als der erste Tag des Monats, der der letzte Tag des vorherigen Monats ist.


1
Es ist okay, ich habe bemerkt, dass die ausgewählte Antwort dasselbe vorschlägt. Dies ist der schnellste und zuverlässigste Weg und funktioniert unabhängig von der Art des Kalenders. Wenn Date beispielsweise etwas anderes als den Gregorianischen Kalender implementiert, funktioniert es immer noch. Unter intldate.codeplex.com finden Sie ein Beispiel für die nicht-gregorianische Implementierung des Date-Objekts.
Orad

1
@orad: Hüten Sie sich davor, etwas "am schnellsten" zu behaupten, da diese Methode tatsächlich erheblich langsamer ist als einige Alternativen. Die Verwendung new Dateist so viel langsamer, dass sie nicht einmal in der Perf-Tabelle angezeigt wird
Gone Coding

@TrueBlueAussie OK. Ich hatte angenommen, dass es schneller war, weil es einheimisch war. Aber du hast recht, es ist nicht schnell. Vielen Dank, dass Sie es tatsächlich getestet haben. Auf jeden Fall funktioniert diese Lösung am besten für mich, da sie übersichtlich und lesbar ist und im Gegensatz zu allen anderen Lösungen nicht an den Gregorianischen Kalender gebunden ist.
Orad

"ist im Gegensatz zu allen anderen Lösungen nicht an den Gregorianischen Kalender gebunden" !!! Dieser Algorithmus gibt die gleichen Werte wie meiner für die Jahre 1 bis 4000 zurück.jsfiddle.net/2973x9m3/3 Welchen zusätzlichen Datumsbereich soll dies unterstützen (was von Nutzen wäre)? :)
Gone Coding

1
Das native JS-Datum verwendet nur den Gregorianischen Kalender. Sie können es jedoch mit einer anderen Implementierung verspotten, um andere Kalendertypen zu erhalten. Zum Beispiel siehe IntlDate . Wenn Sie eine Datumsauswahl haben, die Datumsobjekte zum Erstellen von Monatsansichten verwendet, ist es egal, welche Datumsimplementierung (nativ oder verspottet) verwendet wird, solange sie dieselbe Schnittstelle haben. Die Verwendung einer gemeinsam genutzten Oberfläche ermöglicht also den Wechsel zwischen verschiedenen Kalendertypen, ohne dass Sie wissen müssen, wie viele Tage ein Monat in jedem Kalender hat.
Orad

24

In Bezug auf Computer new Date()und regular expressionLösungen sind langsam! Wenn Sie einen superschnellen (und superkryptischen) Einzeiler wünschen, versuchen Sie diesen (vorausgesetzt, er mist inJan=1 Format). Ich versuche immer wieder, verschiedene Codeänderungen vorzunehmen, um die beste Leistung zu erzielen.

Meine aktuell schnellste Version:

Nachdem ich mir diese verwandte Frage mit Hilfe von bitweisen Operatoren (erstaunliche Geschwindigkeit) angesehen und herausgefunden habe, was die magische Zahl von 25 und 15 darstellt, habe ich diese optimierte Mischung von Antworten gefunden:

function getDaysInMonth(m, y) {
    return m===2 ? y & 3 || !(y%25) && y & 15 ? 28 : 29 : 30 + (m+(m>>3)&1);
}

Angesichts der Bitverschiebung wird offensichtlich davon ausgegangen, dass Ihre m& y-Parameter beide Ganzzahlen sind, da das Übergeben von Zahlen als Zeichenfolgen zu seltsamen Ergebnissen führen würde.

JSFiddle: http://jsfiddle.net/TrueBlueAussie/H89X3/22/

JSPerf-Ergebnisse: http://jsperf.com/days-in-month-head-to-head/5

Aus irgendeinem Grund (m+(m>>3)&1)ist effizienter als (5546>>m&1)in fast allen Browsern.

Die einzige echte Konkurrenz für Geschwindigkeit ist @GitaarLab, daher habe ich eine Kopf-an-Kopf-JSPerf erstellt, die wir testen können: http://jsperf.com/days-in-month-head-to-head/5


Es funktioniert basierend auf meiner Antwort auf das Schaltjahr hier: Javascript Schaltjahr finden diese Antwort hier Leap Jahr Prüfung mit Bitoperatoren (erstaunliche Geschwindigkeit) sowie die folgenden binäre Logik.

Eine kurze Lektion in zwei Monaten:

Wenn Sie den Index der gewünschten Monate interpretieren (Jan = 1) binär Sie feststellen, dass in Monaten mit 31 Tagen entweder Bit 3 gelöscht und Bit 0 gesetzt oder Bit 3 gesetzt und Bit 0 gelöscht ist.

Jan = 1  = 0001 : 31 days
Feb = 2  = 0010
Mar = 3  = 0011 : 31 days
Apr = 4  = 0100
May = 5  = 0101 : 31 days
Jun = 6  = 0110
Jul = 7  = 0111 : 31 days
Aug = 8  = 1000 : 31 days
Sep = 9  = 1001
Oct = 10 = 1010 : 31 days
Nov = 11 = 1011
Dec = 12 = 1100 : 31 days

Das bedeutet können Sie den Wert 3 Plätze mit verschieben >> 3, XOR die Bits mit dem Original ^ mund sehen , ob das Ergebnis 1oder 0 in Bit - Position 0 mit & 1. Hinweis: Es stellt sich heraus, dass +es etwas schneller als XOR ist (^ ) ist und (m >> 3) + min Bit 0 das gleiche Ergebnis liefert.

JSPerf-Ergebnisse : http://jsperf.com/days-in-month-perf-test/6



1
@GitaarLAB: Du hast bereits eine Erwähnung bekommen und diese war nie genau die gleiche wie deine, wie du weißt. Die inkrementelle Aktualisierung der Algorithmen des jeweils anderen ist nicht dasselbe wie "Originalalgo". Ich habe mich auch sehr um diese Antwort bemüht: P
Gone Coding

@TrueBlueAussie: Ich wollte zukünftige Leser nur auf unseren Schatz an mehr Informationen hinweisen (ich habe unsere beiden Antworten verknüpft, damit jeder, der sich darum kümmert oder einen anderen versuchen möchte, in unserer Bearbeitungshistorie nachsehen kann, wann wir was und warum getan haben ). Ich erinnere mich noch gut an unseren ganzen Wettkampftag! :)Die allererste Antwortversion, die ich gepostet habe, hatte tatsächlich einen nicht benötigten Satz Klammern, die entfernt wurden (was ich Ihnen gutgeschrieben habe), damit wir uns von einem Charakter rasieren und mit diesem enden konnten. Ich bin immer noch dankbar für diesen lustigen Tag, Prost!
GitaarLAB

1
Bitte erwähnen Sie das yund mVariablen müssen ganzzahlig sein, nicht string! Es verursacht falsche Berechnungen, zum Beispiel für Februar, es gibt 30 zurück. Ich musste die parseInt()Funktion verwenden, damit es funktioniert.
Stattdessen


16

Eine geringfügige Änderung der von lebreeze bereitgestellten Lösung :

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

Dies sollte return new Date(iYear, 1 + iMonth, 0).getDate();der Lösung von @ lebreeze entsprechen.
Moos

6

Ich musste kürzlich etwas Ähnliches tun, das habe ich mir ausgedacht:

/**
* Returns a date set to the begining of the month
* 
* @param {Date} myDate 
* @returns {Date}
*/
function beginningOfMonth(myDate){    
  let date = new Date(myDate);
  date.setDate(1)
  date.setHours(0);
  date.setMinutes(0);
  date.setSeconds(0);   
  return date;     
}

/**
 * Returns a date set to the end of the month
 * 
 * @param {Date} myDate 
 * @returns {Date}
 */
function endOfMonth(myDate){
  let date = new Date(myDate);
  date.setMonth(date.getMonth() +1)
  date.setDate(0);
  date.setHours(23);
  date.setMinutes(59);
  date.setSeconds(59);
  return date;
}

Übergeben Sie ein Datum, und es wird ein Datum zurückgegeben, das entweder auf den Monatsanfang oder das Monatsende festgelegt ist.

Die begninngOfMonthFunktion ist ziemlich selbsterklärend, aber was in der endOfMonthFunktion vor sich geht, ist, dass ich den Monat auf den nächsten Monat inkrementiere und dann verwendesetDate(0) den Tag auf den letzten Tag des vorherigen Monats zurücksetze, der Teil des ist setDate spec:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/setDate https://www.w3schools.com/jsref/jsref_setdate.asp

Ich habe dann die Stunde / Minuten / Sekunden auf das Ende des Tages gesetzt, damit Sie, wenn Sie eine API verwenden, die einen Datumsbereich erwartet, den gesamten letzten Tag erfassen können. Dieser Teil könnte über das hinausgehen, was der ursprüngliche Beitrag verlangt, aber er könnte jemand anderem helfen, nach einer ähnlichen Lösung zu suchen.

Bearbeiten: Sie können auch die Extrameile gehen und Millisekunden einstellen, setMilliseconds()wenn Sie besonders präzise sein möchten.


4

Probier diese.

lastDateofTheMonth = new Date(year, month, 0)

Beispiel:

new Date(2012, 8, 0)

Ausgabe:

Date {Fri Aug 31 2012 00:00:00 GMT+0900 (Tokyo Standard Time)}

5
Denken Sie jedoch daran, dass die Monate auf Null basieren. Wenn Sie also "8" überschreiten, ist der Monat wirklich September und nicht August.
Steve J

3

Das funktioniert bei mir. Gibt den letzten Tag des angegebenen Jahres und Monats an:

var d = new Date(2012,02,0);
var n = d.getDate();
alert(n);

Seien Sie vorsichtig mit der 0 vor der "2", sie wird als oktal interpretiert.
Walfrat

1

Dieser funktioniert gut:

Date.prototype.setToLastDateInMonth = function () {

    this.setDate(1);
    this.setMonth(this.getMonth() + 1);
    this.setDate(this.getDate() - 1);

    return this;
}

1

Dies gibt Ihnen den ersten und letzten Tag des aktuellen Monats.

Wenn Sie 'Jahr' ändern müssen, entfernen Sie d.getFullYear () und legen Sie Ihr Jahr fest.

Wenn Sie 'Monat' ändern müssen, entfernen Sie d.getMonth () und legen Sie Ihr Jahr fest.

var d = new Date();
var days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
var fistDayOfMonth = days[(new Date(d.getFullYear(), d.getMonth(), 1).getDay())];
	var LastDayOfMonth = days[(new Date(d.getFullYear(), d.getMonth() + 1, 0).getDay())]; 
console.log("First Day :" + fistDayOfMonth); 
console.log("Last Day:" + LastDayOfMonth);
alert("First Day :" + fistDayOfMonth); 
alert("Last Day:" + LastDayOfMonth);


1

Versuche dies:

function _getEndOfMonth(time_stamp) {
    let time = new Date(time_stamp * 1000);
    let month = time.getMonth() + 1;
    let year = time.getFullYear();
    let day = time.getDate();
    switch (month) {
        case 1:
        case 3:
        case 5:
        case 7:
        case 8:
        case 10:
        case 12:
            day = 31;
            break;
        case 4:
        case 6:
        case 9:
        case 11:
            day = 30;
            break;
        case 2:
            if (_leapyear(year))
                day = 29;
            else
                day = 28;
            break
    }
    let m = moment(`${year}-${month}-${day}`, 'YYYY-MM-DD')
    return m.unix() + constants.DAY - 1;
}

function _leapyear(year) {
    return (year % 100 === 0) ? (year % 400 === 0) : (year % 4 === 0);
}

1

Die folgende Funktion gibt den letzten Tag des Monats an:

function getLstDayOfMonFnc(date) {
  return new Date(date.getFullYear(), date.getMonth(), 0).getDate()
}

console.log(getLstDayOfMonFnc(new Date(2016, 2, 15))) // Output : 29
console.log(getLstDayOfMonFnc(new Date(2017, 2, 15))) // Output : 28
console.log(getLstDayOfMonFnc(new Date(2017, 11, 15))) // Output : 30
console.log(getLstDayOfMonFnc(new Date(2017, 12, 15))) // Output : 31

Ebenso können wir den ersten Tag des Monats bekommen:

function getFstDayOfMonFnc(date) {
  return new Date(date.getFullYear(), date.getMonth(), 1).getDate()
}

console.log(getFstDayOfMonFnc(new Date(2016, 2, 15))) // Output : 1


0
function getLastDay(y, m) {
   return 30 + (m <= 7 ? ((m % 2) ? 1 : 0) : (!(m % 2) ? 1 : 0)) - (m == 2) - (m == 2 && y % 4 != 0 || !(y % 100 == 0 && y % 400 == 0)); 
}

0
const today = new Date();

let beginDate = new Date();

let endDate = new Date();

// fist date of montg

beginDate = new Date(

  `${today.getFullYear()}-${today.getMonth() + 1}-01 00:00:00`

);

// end date of month 

// set next Month first Date

endDate = new Date(

  `${today.getFullYear()}-${today.getMonth() + 2}-01 :23:59:59`

);

// deducting 1 day

endDate.setDate(0);

0

Stellen Sie den Monat ein, den Sie datieren müssen, und setzen Sie dann den Tag auf Null, sodass der Monat in der Datumsfunktion 1 - 31 beginnt und dann den letzten Tag erhält ^^

var last = new Date(new Date(new Date().setMonth(7)).setDate(0)).getDate();
console.log(last);


0

Hier ist eine Antwort, bei der GMT und die Uhrzeit des ursprünglichen Datums erhalten bleiben

var date = new Date();

var first_date = new Date(date); //Make a copy of the date we want the first and last days from
first_date.setUTCDate(1); //Set the day as the first of the month

var last_date = new Date(first_date); //Make a copy of the calculated first day
last_date.setUTCMonth(last_date.getUTCMonth() + 1); //Add a month
last_date.setUTCDate(0); //Set the date to 0, this goes to the last day of the previous month

console.log(first_date.toJSON().substring(0, 10), last_date.toJSON().substring(0, 10)); //Log the dates with the format yyyy-mm-dd


0

Ich weiß, dass es nur um Semantik geht, aber ich habe es letztendlich in dieser Form verwendet.

var lastDay = new Date(new Date(2008, 11+1,1) - 1).getDate();
console.log(lastDay);

Da Funktionen vom inneren Argument nach außen aufgelöst werden, funktioniert es genauso.

Sie können dann einfach das Jahr und den Monat / das Jahr durch die erforderlichen Details ersetzen, unabhängig davon, ob es sich um das aktuelle Datum handelt. Oder einen bestimmten Monat / ein bestimmtes Jahr.


0

Wenn Sie das genaue Monatsende in Millisekunden benötigen (z. B. in einem Zeitstempel):

d = new Date()
console.log(d.toString())
d.setDate(1)
d.setHours(23, 59, 59, 999)
d.setMonth(d.getMonth() + 1)
d.setDate(d.getDate() - 1)
console.log(d.toString())

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.