Calcola l'ultimo giorno del mese in JavaScript


277

Se si fornisce 0come dayValueinDate.setFullYear si ottiene l'ultimo giorno del mese precedente:

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

C'è riferimento a questo comportamento su Mozilla . È una funzionalità affidabile per più browser o dovrei esaminare metodi alternativi?


Non intendi l'ultimo giorno del mese specificato? Ci sono 30 giorni a novembre e 31 ad ottobre.
Chris Serra,

16
I mesi sono a base zero in javascript, quindi l'11 è dicembre
Greg,

2
@TheCloudlessSky - provalo nella tua console ... (2008,11,0) è il giorno zero di dicembre, e quindi l'ultimo giorno di novembre
Ken

@Ken - Sì - Non mi rendevo conto che c'era uno "0":) ... era troppo presto la mattina.
TheCloudlessSky

Risposte:


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

Le differenze di output sono dovute a differenze toString()nell'implementazione, non perché le date sono diverse.

Naturalmente, solo perché i browser identificati sopra usano 0 come l'ultimo giorno del mese precedente non significa che continueranno a farlo, o che i browser non elencati lo faranno, ma presta credibilità alla convinzione che dovrebbe funzionare allo stesso modo in ogni browser.


19
Sembra funzionare perfettamente. Per curiosità, cosa stai usando per eseguire il javascript su tutti questi motori? Hai tutto pronto o qualche tipo di strumento?
Neonski,

5
puoi usare d.getDate () per ottenere il giorno reale.
rynop

35
"solo perché i browser ... usano 0 come ultimo giorno del mese precedente non significa che continueranno a farlo". Sì, sono tenuti a farlo dall'ECMA-262.
RobG

3
Si prega di notare che l'utilizzo new Dateè così molto più lento rispetto ad altri metodi di calcolo che non mostra anche fino sul grafico perf : jsperf.com/days-in-month-perf-test/6
Andato Coding

4
Non funziona per me su Chrome 48.0.2564.116. Forse, in questo modo ha smesso di essere lo "standard".
xarlymg89,

77

Vorrei utilizzare una data intermedia con il primo giorno del mese successivo e restituire la data del giorno precedente:

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

Secondo le specifiche ECMAScript , è valido l'utilizzo del costruttore "Date" come hai sottolineato. Seguendo l'algoritmo specificato dalla funzione "MakeDay", dovrebbe gestire bene il problema.
Pablo Cabrera,

1
questa è la migliore soluzione IMO. Ho provato la risposta accettata ma presenta alcuni bug durante il recupero dell'ultimo mese corrente. Restituisce la data di oggi. Non sono sicuro del perché ciò accada però.
Gogol,

1
Non riesco a ripetere il bug. Questo mi dà la data corretta in tutti i browser:today = new Date(); new Date(today.getFullYear(), today.getMonth()+1, 0).toString();
orad

Questo crea un oggetto Date per l'ultimo giorno del mese con l'ora impostata sull'ultimo millisecondo (ovvero 23: 59: 59.999). Meglio usare solo il metodo nell'OP e salvare il passaggio extra e l'oggetto Date.
RobG

@RobG: sono d'accordo! anche se la mia soluzione potrebbe essere più facile da capire, dato che l'idea di usare 0 per l'ultimo giorno del mese sembra un po 'cluncky secondo me.
karlipoppins

72

Trovo che questa sia la soluzione migliore per me. Lascia che l'oggetto Date lo calcoli per te.

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

Impostando il parametro day su 0 si intende un giorno in meno rispetto al primo giorno del mese che è l'ultimo giorno del mese precedente.


1
Va bene, ho notato che la risposta selezionata suggerisce lo stesso. Questo è il modo più veloce e affidabile e funziona indipendentemente dal tipo di calendario. Ad esempio, se Date implementasse qualcosa di diverso dal calendario gregoriano, funzionerebbe comunque. Vedi intldate.codeplex.com per un esempio di implementazione non gregoriana dell'oggetto Date.
orad,

1
@orad: attenzione a dichiarare che "è il più veloce" in quanto questo metodo è notevolmente più lento di alcune alternative. Usando new Dateè così molto più lento che non mostra anche fino sul grafico perf : jsperf.com/days-in-month-perf-test/6
Andato Coding

@TrueBlueAussie OK. Avevo supposto che fosse più veloce perché era nativo. Ma hai ragione, non è veloce. Grazie per averlo testato. Comunque, questa soluzione funziona meglio per me perché è concisa e leggibile e, a differenza di tutte le altre soluzioni, non è legata al calendario gregoriano.
orad,

"a differenza di tutte le altre soluzioni non è legata al calendario gregoriano" !!! Questo algoritmo restituisce gli stessi valori dei miei per anni 1-4000. jsfiddle.net/2973x9m3/3 Quale intervallo di date aggiuntivo stai sostenendo che ciò supporterà (sarebbe utile)? :)
Codice andato finito il

1
Native JS Date utilizza solo il calendario gregoriano. Ma potresti deriderlo con qualche altra implementazione per ottenere altri tipi di calendario. Ad esempio, vedi IntlDate . Se disponi di un selettore di date che utilizza gli oggetti Date per creare visualizzazioni mensili, non importa quale implementazione Data (nativa o derisa) stia utilizzando fintanto che hanno la stessa interfaccia. Pertanto, l'utilizzo di un'interfaccia condivisa consente il passaggio tra diversi tipi di calendario senza dover sapere quanti giorni sono in un mese su ciascun calendario.
orad,

25

In termini informatici, new Date()e le regular expressionsoluzioni sono lente! Se vuoi un one-liner super veloce (e super criptico), prova questo (supponendo che msia dentroJan=1 formato). Continuo a provare diverse modifiche al codice per ottenere le migliori prestazioni.

La mia attuale versione più veloce :

Dopo aver esaminato questa domanda correlata Verifica dell'anno bisestile utilizzando operatori bit per bit (velocità incredibile) e scoperto cosa rappresentava il numero magico 25 e 15, ho trovato questo ibrido ottimizzato di risposte:

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

Dato lo spostamento dei bit, ciò presuppone ovviamente che il tuo m&y parametri siano entrambi numeri interi, poiché il passaggio di numeri come stringhe comporterebbe risultati strani.

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

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

Per qualche motivo, (m+(m>>3)&1)è più efficiente rispetto (5546>>m&1)a quasi tutti i browser.

L'unica vera competizione per la velocità è di @GitaarLab, quindi ho creato un JSPerf testa a testa su cui testare: http://jsperf.com/days-in-month-head-to-head/5


Funziona in base alla mia risposta dell'anno bisestile qui: javascript per trovare l'anno bisestile questa risposta qui Controllo anno bisestile utilizzando operatori bit a bit (velocità incredibile) e la seguente logica binaria.

Una breve lezione in mesi binari:

Se si interpreta l'indice dei mesi desiderati (Jan = 1) in binario, si noterà che i mesi con 31 giorni hanno bit 3 azzerato e bit 0 impostato, oppure bit 3 impostato e bit 0 azzerato.

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

Ciò significa che puoi spostare il valore di 3 posizioni con >> 3, XOR i bit con l'originale ^ me vedere se il risultato è 1o 0 nella posizione di bit 0 usando & 1. Nota: risulta +leggermente più veloce di XOR ( ^) e (m >> 3) + mfornisce lo stesso risultato nel bit 0.

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



1
@GitaarLAB: hai già ricevuto una menzione e questo non è mai stato esattamente uguale al tuo, come ben sai. L'aggiornamento incrementale di ogni altro algoritmo non è lo stesso di "algo originale". Mi sono impegnato molto anche in questa risposta: P
Gone Coding

@TrueBlueAussie: volevo solo indirizzare i futuri lettori al nostro tesoro di maggiori informazioni (ho collegato entrambe le nostre risposte in modo che chiunque si preoccupi o voglia fare un altro tentativo possa guardare la nostra cronologia delle modifiche per vedere quando abbiamo fatto cosa e perché ). Ricordo ancora con affetto la nostra intera giornata di gare! :)La primissima versione di risposta che ho pubblicato aveva effettivamente una serie di parentesi non necessarie, che sono state rimosse (per le quali ti ho accreditato) in modo da poter radere un personaggio e finire con questo. Sono ancora grato per quel giorno divertente, evviva!
GitaarLAB,

1
Si prega di ricordare che ye mvariabili devono essere intero non stringa! Causa calcoli errati, ad esempio per febbraio restituisce 30. Ho dovuto usare la parseInt()funzione per farlo funzionare.
invece il

21

Il mio collega si è imbattuto in ciò che potrebbe essere una soluzione più semplice

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

rubato da http://snippets.dzone.com/posts/show/2099


2
Nigel lo ha modificato in una soluzione ancora più concisa. Vedi il suo post.
orad

Il mese è a base zero, ovvero Jan = 0. Come getMonth ().
Moos,

16

Una leggera modifica alla soluzione fornita da lebreeze :

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

Questo dovrebbe essere return new Date(iYear, 1 + iMonth, 0).getDate();equivalente alla soluzione di @ lebreeze.
Moos,

6

Di recente ho dovuto fare qualcosa di simile, ecco cosa mi è venuto in mente:

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

Passalo in una data e restituirà una data impostata all'inizio del mese o alla fine del mese.

La begninngOfMonthfunzione è abbastanza autoesplicativa, ma quello che sta succedendo nella endOfMonthfunzione è che sto incrementando il mese al mese successivo e quindi usandosetDate(0) per ripristinare il giorno all'ultimo giorno del mese precedente che fa parte del setDate spec:

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

Ho quindi impostato l'ora / minuti / secondi alla fine della giornata, in modo che se si utilizza un tipo di API che si aspetta un intervallo di date, sarà possibile acquisire l'intero ultimo giorno. Quella parte potrebbe andare oltre quanto richiesto dal post originale, ma potrebbe aiutare qualcun altro a cercare una soluzione simile.

Modifica: puoi anche fare il miglio supplementare e impostare i millisecondi con setMilliseconds() se vuoi essere più preciso.


4

prova questo.

lastDateofTheMonth = new Date(year, month, 0)

esempio:

new Date(2012, 8, 0)

produzione:

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

5
Ricorda, tuttavia, che i mesi sono a base zero, quindi passa "8" dato che il mese è davvero settembre, non agosto.
Steve J,

3

Questo funziona per me. Fornirà l'ultimo giorno di un determinato anno e mese:

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

1
fai attenzione con lo 0 davanti al "2", verrà interpretato come ottale.
Walfrat,

1

Questo funziona bene:

Date.prototype.setToLastDateInMonth = function () {

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

    return this;
}

1

Questo ti darà il mese corrente il primo e l'ultimo giorno.

Se è necessario modificare "anno", rimuovere d.getFullYear () e impostare l'anno.

Se è necessario cambiare 'mese', rimuovere d.getMonth () e impostare l'anno.

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

Prova questo:

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

La funzione seguente indica l'ultimo giorno del mese:

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

Allo stesso modo possiamo ottenere il primo giorno del mese:

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

impostare il mese che è necessario datare e quindi impostare il giorno su zero, quindi il mese inizia con la funzione di data 1 - 31, quindi si ottiene l'ultimo giorno ^^

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


0

Ecco una risposta che conserva GMT e ora della data iniziale

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

So che è solo una questione di semantica, ma ho finito per usarlo in questo modulo.

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

Poiché le funzioni sono risolte dall'argomento interno, verso l'esterno, funziona allo stesso modo.

È quindi possibile sostituire l'anno e il mese / anno con i dettagli richiesti, indipendentemente dalla data corrente. O un mese / anno particolare.


0

Se hai bisogno della fine esatta del mese in millisecondi (ad esempio in un timestamp):

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.