Calcule el último día del mes en JavaScript

277

Si usted proporciona 0como el dayValuede Date.setFullYearusted consigue el último día del mes anterior:

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

Hay referencia a este comportamiento en mozilla . ¿Es esta una característica confiable de navegador cruzado o debería buscar métodos alternativos?

Conocido
fuente
¿No te refieres al último día del mes especificado? Hay 30 días en noviembre y 31 en octubre.
Chris Serra
16
Los meses están basados ​​en cero en javascript, así que el 11 es diciembre
Greg
2
@TheCloudlessSky: pruébelo en su consola ... (2008,11,0) es el día cero de diciembre y, por lo tanto, el último día de noviembre
Ken
@Ken - Sí, no me di cuenta de que había un "0":) ... era muy temprano en la mañana.
TheCloudlessSky

Respuestas:

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)

Las diferencias de salida se deben a diferencias en la toString()implementación, no porque las fechas sean diferentes.

Por supuesto, solo porque los navegadores identificados anteriormente usan 0 como el último día del mes anterior no significa que continuarán haciéndolo, o que los navegadores que no figuran en la lista lo harán, pero le da credibilidad a la creencia de que debería funcionar. De la misma manera en todos los navegadores.

Grant Wagner
fuente
19
Eso parece funcionar perfectamente bien. Por curiosidad, ¿qué estás utilizando para ejecutar el JavaScript en todos estos motores? ¿Tienes todo configurado o algún tipo de herramienta?
neonski
55
puede usar d.getDate () para obtener el día real.
rynop
35
"solo porque los navegadores ... usen 0 como el último día del mes anterior no significa que continuarán haciéndolo". Sí, lo requiere ECMA-262.
RobG
3
Tenga en cuenta que el uso new Datees por lo tanto más lento que otros métodos de cálculo que ni siquiera aparece en el gráfico Potencia : jsperf.com/days-in-month-perf-test/6
Gone Codificación
44
No me funciona en Chrome 48.0.2564.116. Quizás, esta manera ha dejado de ser el 'estándar'.
xarlymg89
77

Usaría una fecha intermedia con el primer día del mes siguiente y devolvería la fecha del día anterior:

int_d = new Date(2008, 11+1,1);
d = new Date(int_d - 1);
karlipoppins
fuente
De acuerdo con la especificación ECMAScript , es válido hacer uso del constructor "Fecha" como usted señaló. Siguiendo el algoritmo especificado por la función "MakeDay", debería manejar el problema muy bien.
Pablo Cabrera
1
Esta es la mejor solución de la OMI. Intenté la respuesta aceptada pero tiene algún error al recuperar el último del mes actual. Devuelve la fecha de hoy. Sin embargo, no estoy seguro de por qué sucede eso.
Gogol
1
No puedo reprobar el error. Esto me da la fecha correcta en todos los navegadores:today = new Date(); new Date(today.getFullYear(), today.getMonth()+1, 0).toString();
orad
Esto crea un objeto Date para el último día del mes con la hora establecida en el último milisegundo (es decir, 23: 59: 59.999). Es mejor usar el método en el OP y guardar el paso adicional y el objeto Date.
RobG
@RobG: estoy de acuerdo! aunque mi solución podría ser más fácil de entender, ya que la noción de usar 0 para el último día del mes se siente un poco torpe en mi opinión.
karlipoppins
72

Creo que esta es la mejor solución para mí. Deje que el objeto Fecha lo calcule por usted.

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

Establecer el parámetro del día en 0 significa un día menos que el primer día del mes, que es el último día del mes anterior.

orad
fuente
1
Está bien, noté que la respuesta seleccionada sugiere lo mismo. Esta es la forma más rápida y confiable y funciona independientemente del tipo de calendario. Por ejemplo, si Date implementara algo diferente al calendario gregoriano, todavía funcionaría. Consulte intldate.codeplex.com para ver un ejemplo de implementación no gregoriana del objeto Date.
orad
1
@orad: Tenga cuidado de decir que "es el más rápido", ya que este método es considerablemente más lento que algunas alternativas. El uso new Datees tan mucho más lento que ni siquiera aparece en el gráfico Potencia : jsperf.com/days-in-month-perf-test/6
Gone Codificación
@TrueBlueAussie OK. Supuse que era más rápido porque era nativo. Pero tienes razón, no es rápido. Gracias por probarlo realmente. De todos modos, esta solución funciona mejor para mí porque es concisa y legible y, a diferencia de todas las demás soluciones, no está vinculada al calendario gregoriano.
orad
"¡a diferencia de todas las demás soluciones, no está vinculado al calendario gregoriano"! Este algoritmo devuelve los mismos valores que el mío para los años 1-4000. jsfiddle.net/2973x9m3/3 ¿Qué intervalo de fechas adicional está reclamando que esto admitirá (que sería útil)? :)
Se fue la codificación
1
Native JS Date usa solo el calendario gregoriano. Pero podría simularlo con alguna otra implementación para obtener otros tipos de calendario. Por ejemplo, vea IntlDate . Si tiene un selector de fecha que usa objetos de Fecha para crear vistas mensuales, no le importa qué implementación de Fecha (nativa o simulada) esté usando siempre que tengan la misma interfaz. Por lo tanto, el uso de una interfaz compartida permite cambiar entre diferentes tipos de calendario sin tener que saber cuántos días hay en un mes en cada calendario.
orad
25

En términos informáticos, ¡ new Date()y las regular expressionsoluciones son lentas! Si quieres un trazador de líneas súper rápido (y súper críptico), prueba este (suponiendo que mesté enJan=1 formato). Sigo probando diferentes cambios de código para obtener el mejor rendimiento.

Mi versión más rápida actual :

Después de ver esta pregunta relacionada, verifique el año bisiesto utilizando operadores bit a bit (velocidad sorprendente) y descubra lo que representaban los números mágicos 25 y 15, se me ocurrió este híbrido optimizado de respuestas:

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

Dado el cambio de bits, esto obviamente supone que sus parámetros m& yson ambos enteros, ya que pasar números como cadenas daría como resultado resultados extraños.

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

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

Por alguna razón, (m+(m>>3)&1)es más eficiente que (5546>>m&1)en casi todos los navegadores.

La única competencia real por la velocidad es de @GitaarLab, así que he creado un JSPerf cabeza a cabeza para que podamos probarlo en: http://jsperf.com/days-in-month-head-to-head/5


Funciona en función de la respuesta de mi año bisiesto aquí: javascript para encontrar el año bisiesto esta respuesta aquí Verificación del año bisiesto utilizando operadores bit a bit (velocidad sorprendente) así como la siguiente lógica binaria.

Una lección rápida en meses binarios:

Si interpreta el índice de los meses deseados (Jan = 1) en binario , notará que los meses con 31 días tienen el bit 3 claro y el bit 0 establecido, o el bit 3 establecido y el bit 0 claro.

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

Eso significa que puede cambiar el valor 3 lugares con >> 3, XOR los bits con el original ^ my ver si el resultado está 1o 0 en la posición de bit 0 usando & 1. Nota: Resulta que +es un poco más rápido que XOR ( ^) y (m >> 3) + mda el mismo resultado en el bit 0.

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

Codificación ido
fuente
1
@GitaarLAB: Ya tienes una mención y esto nunca fue exactamente igual al tuyo, como bien sabes. La actualización incremental de los algoritmos de los demás no es lo mismo que "algo original". También puse mucho esfuerzo en esta respuesta: P
Gone Coding
@TrueBlueAussie: solo quería señalar a los futuros lectores nuestro tesoro de más información (vinculé ambas respuestas para que cualquiera que le interese o quiera intentarlo de nuevo pueda ver nuestro historial de edición para ver cuándo hicimos qué y por qué ) ¡Todavía recuerdo con cariño nuestro día completo de competencia! :)La primera versión de respuesta que publiqué tenía un conjunto innecesario de corchetes, que fueron eliminados (por lo que te atribuí) para que pudiéramos afeitarnos de un personaje y terminar con este. Todavía estoy agradecido por ese día divertido, ¡salud!
GitaarLAB
1
¡Mencione eso yy las mvariables tienen que ser enteras, no cadenas! Causa cálculos incorrectos, por ejemplo, para febrero devuelve 30. Tuve que usar la parseInt()función para que funcione.
lugar del
21

Mi colega se topó con lo siguiente, que puede ser una solución más fácil

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

robado de http://snippets.dzone.com/posts/show/2099

Lebreeze
fuente
2
Nigel modificó esto a una solución aún más concisa. Ver su post.
Orad
El mes está basado en cero, es decir, Jan = 0. Igual que getMonth ().
Moos
16

Una ligera modificación a la solución proporcionada por lebreeze :

function daysInMonth(iMonth, iYear)
{
    return new Date(iYear, iMonth, 0).getDate();
}
Nigel
fuente
Esto debería ser return new Date(iYear, 1 + iMonth, 0).getDate();equivalente a la solución de @lebreeze.
Moos
6

Recientemente tuve que hacer algo similar, esto es lo que se me ocurrió:

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

Pásalo en una fecha y devolverá una fecha establecida a principios de mes o al final del mes.

La begninngOfMonthfunción se explica por sí misma, pero lo que está sucediendo en la endOfMonthfunción es que estoy incrementando el mes al siguiente mes, y luego lo uso setDate(0)para retroceder el día hasta el último día del mes anterior, que es parte del Especificación setDate:

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

Luego establezco la hora / minutos / segundos al final del día, de modo que si está utilizando algún tipo de API que espera un rango de fechas, podrá capturar la totalidad de ese último día. Esa parte podría ir más allá de lo que pide la publicación original, pero podría ayudar a alguien más a buscar una solución similar.

Editar: También puede hacer un esfuerzo adicional y configurar milisegundos setMilliseconds()si desea ser más preciso.

Eric
fuente
4

prueba este.

lastDateofTheMonth = new Date(year, month, 0)

ejemplo:

new Date(2012, 8, 0)

salida:

Date {Fri Aug 31 2012 00:00:00 GMT+0900 (Tokyo Standard Time)}
artsylar
fuente
55
Sin embargo, recuerde que los meses están basados ​​en cero, por lo que pasar "8" ya que el mes es realmente septiembre, no agosto.
Steve J
3

Esto funciona para mi. Proporcionará el último día del año y mes dado:

var d = new Date(2012,02,0);
var n = d.getDate();
alert(n);
Kreeverp
fuente
1
tenga cuidado con el 0 delante del "2", se interpretará como octal.
Walfrat
1

Este funciona muy bien:

Date.prototype.setToLastDateInMonth = function () {

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

    return this;
}
Josue
fuente
1

Esto le dará el primer y último día del mes actual.

Si necesita cambiar 'año', elimine d.getFullYear () y configure su año.

Si necesita cambiar 'mes', elimine d.getMonth () y configure su año.

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

Himanshu kukreja
fuente
1

Prueba esto:

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);
}
Yatin Darmwal
fuente
1

La siguiente función muestra el último día del mes:

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

Del mismo modo podemos obtener el primer día del mes:

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

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

Sujay UN
fuente
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)); 
}
Ashish
fuente
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);
chou
fuente
0

establezca el mes que necesita para la fecha y luego configure el día en cero, por lo que el mes comienza en 1 - 31 en la función de fecha y luego obtiene el último día ^^

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

ahmed samra
fuente
0

Aquí hay una respuesta que conserva GMT y la hora de la fecha inicial

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

Tofandel
fuente
0

Sé que es solo una cuestión de semántica, pero terminé usándolo de esta forma.

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

Como las funciones se resuelven desde el argumento interno, hacia afuera, funciona igual.

Luego puede reemplazar el año y el mes / año con los detalles requeridos, ya sea a partir de la fecha actual. O un mes / año en particular.

Rudi Strydom
fuente
0

Si necesita el final exacto del mes en milisegundos (por ejemplo, en una marca de tiempo):

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

Gungnir
fuente