Calcular o último dia do mês em JavaScript

277

Se você fornecer 0como a dayValueem Date.setFullYearque você começa o último dia do mês anterior:

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

Há referência a esse comportamento no mozilla . Esse é um recurso confiável entre navegadores ou devo procurar métodos alternativos?

Ken
fonte
Você não quis dizer o último dia do mês especificado? Há 30 dias em novembro e 31 em outubro.
Chris Serra
16
Os meses são baseados em zero em javascript, então 11 é dezembro
Greg
2
@TheCloudlessSky - experimente no seu console ... (2008,11,0) é o dia zero de dezembro e, portanto, o último dia de novembro
Ken
@ Ken - Sim - eu não sabia que havia um "0":) ... era muito cedo pela manhã.
TheCloudlessSky

Respostas:

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)

As diferenças de saída são devidas a diferenças na toString()implementação, não porque as datas são diferentes.

Obviamente, apenas porque os navegadores identificados acima usam 0 como o último dia do mês anterior não significa que eles continuarão a fazê-lo ou que os navegadores não listados o farão, mas isso dá credibilidade à crença de que ele deve funcionar de maneira adequada. da mesma maneira em todos os navegadores.

Grant Wagner
fonte
19
Isso parece funcionar perfeitamente bem. Por curiosidade, o que você está usando para executar o javascript em todos esses mecanismos? Tem tudo configurado ou algum tipo de ferramenta?
21408 neonski
5
você pode usar d.getDate () para obter o dia real.
Rynop
35
"só porque os navegadores ... usam 0 como o último dia do mês anterior não significa que continuarão a fazê-lo". Sim, eles precisam fazê-lo pelo ECMA-262.
RobG
3
Por favor, note que o uso new Dateé por isso muito mais lento do que outros métodos de cálculo que nem sequer aparecem no gráfico perf : jsperf.com/days-in-month-perf-test/6
Ido Codificação
4
Não funciona para mim no Chrome 48.0.2564.116. Talvez esse caminho tenha deixado de ser o "padrão".
xarlymg89
77

Eu usaria uma data intermediária no primeiro dia do mês seguinte e retornaria a data do dia anterior:

int_d = new Date(2008, 11+1,1);
d = new Date(int_d - 1);
karlipoppins
fonte
De acordo com a especificação ECMAScript , é válido o uso do construtor "Data", como você apontou. Seguindo o algoritmo especificado pela função "MakeDay", ele deve lidar bem com o problema.
Pablo Cabrera
1
esta é a melhor solução IMO. Tentei a resposta aceita, mas há algum erro ao buscar o último mês do mês atual. Retorna a data de hoje. Não sei por que isso acontece embora.
Gogol
1
Não consigo reproduzir o bug. Isso me dá a data correta em todos os navegadores:today = new Date(); new Date(today.getFullYear(), today.getMonth()+1, 0).toString();
ou
Isso cria um objeto Date para o último dia do mês com a hora definida para o último milissegundo (ou seja, 23: 59: 59.999). Melhor usar apenas o método no OP e salvar a etapa extra e o objeto Data.
RobG
@RobG: eu concordo! embora minha solução possa ser mais fácil de entender, pois a noção de usar 0 para o último dia do mês parece um pouco irregular na minha opinião.
karlipoppins
72

Acho que essa é a melhor solução para mim. Deixe o objeto Data calculá-lo para você.

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

Definir o parâmetro day como 0 significa um dia a menos que o primeiro dia do mês, que é o último dia do mês anterior.

orad
fonte
1
Tudo bem, notei que a resposta selecionada está sugerindo o mesmo. Essa é a maneira mais rápida e confiável e funciona independentemente do tipo de calendário. Por exemplo, se o Date implementasse algo diferente do calendário gregoriano, ele ainda funcionaria. Consulte intldate.codeplex.com para obter um exemplo de implementação não gregoriana do objeto Date.
orad 12/03/2013
1
@orad: Cuidado com o fato de reivindicar algo "é o mais rápido", pois esse método é realmente consideravelmente mais lento do que algumas alternativas. Usando new Dateé assim muito mais lento que nem sequer aparecem no gráfico perf : jsperf.com/days-in-month-perf-test/6
Ido Codificação
@TrueBlueAussie OK. Eu tinha assumido que era mais rápido porque era nativo. Mas você está certo, não é rápido. Obrigado por realmente testá-lo. De qualquer forma, esta solução funciona melhor para mim porque é concisa e legível e, ao contrário de todas as outras soluções, não está vinculada ao calendário gregoriano.
orad 23/02/15
"ao contrário de todas as outras soluções, não está vinculado ao calendário gregoriano" !!! Esse algoritmo retorna os mesmos valores que o meu para os anos 1-4000. jsfiddle.net/2973x9m3/3 Que período adicional você está reivindicando que isso oferecerá suporte (que seria útil)? :)
Gone Coding
1
A Data JS nativa usa apenas o calendário gregoriano. Mas você pode zombar dele com alguma outra implementação para obter outros tipos de calendário. Por exemplo, consulte IntlDate . Se você tiver um seletor de datas que use objetos Date para criar visualizações mensais, não se importará com qual implementação de Data (nativa ou zombada) está usando, desde que tenham a mesma interface. Portanto, o uso de uma interface compartilhada permite alternar entre diferentes tipos de calendário sem precisar saber quantos dias há um mês em cada calendário.
orad 23/02/15
25

Em termos de computador, new Date()e as regular expressionsoluções são lentas! Se você deseja uma linha única super-rápida (e super-enigmática), tente esta (assumindo que mesteja no Jan=1formato). Continuo tentando diferentes alterações de código para obter o melhor desempenho.

Minha versão mais rápida atual :

Depois de analisar esta questão relacionada , verificar o ano bissexto usando operadores bit a bit (velocidade incrível) e descobrir o que os números mágicos 25 e 15 representavam, eu vim com esse híbrido otimizado de respostas:

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

Dada a mudança de bits, isso obviamente pressupõe que seus parâmetros m& ysão números inteiros, pois a passagem de números e seqüências de caracteres resultaria em resultados estranhos.

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

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

Por alguma razão, (m+(m>>3)&1)é mais eficiente do que (5546>>m&1)em quase todos os navegadores.

A única competição real de velocidade é do @GitaarLab, então eu criei um JSPerf frente a frente para testarmos: http://jsperf.com/days-in-month-head-to-head/5


Funciona com base na minha resposta do ano bissexto aqui: javascript para encontrar o ano bissexto esta resposta aqui Verifique o ano bissexto usando operadores bit a bit (velocidade incrível) , bem como a seguinte lógica binária.

Uma rápida lição em meses binários:

Se você interpretar o índice dos meses desejados (Jan = 1) em binário , notará que meses com 31 dias têm o bit 3 claro e o bit 0 definido ou o bit 3 definido e o bit 0 limpo.

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

Isso significa que você pode mudar o valor 3 lugares com >> 3, XOR os bits com o original ^ me ver se o resultado está 1ou 0 na posição de bit 0 usando & 1. Nota: Acontece que +é um pouco mais rápido que XOR ( ^) e (m >> 3) + mfornece o mesmo resultado no bit 0.

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

Gone Coding
fonte
Algo original e histórico completo (consulte os comentários): stackoverflow.com/questions/1810984/number-of-days-in-any-month/… seguido por stackoverflow.com/questions/1810984/number-of-days-in-any
-month
1
@GitaarLAB: Você já mencionou e nunca foi exatamente igual ao seu, como você bem sabe. A atualização incremental dos algoritmos uns dos outros não é a mesma coisa que "algo original". Também dediquei muito esforço a essa resposta: P
Gone Coding
@TrueBlueAussie: Eu só queria apontar futuros leitores para o nosso tesouro de mais informações (eu vinculei nossas duas respostas para que qualquer pessoa que se preocupe ou que queira tentar outra vez possa olhar para ele possa ver nosso histórico de edições para ver quando fizemos o que e por quê ) Ainda me lembro com carinho do dia inteiro de competição! :)A primeira versão-resposta que publiquei tinha, de fato, um conjunto desnecessário de colchetes, que foram removidos (pelos quais eu creditei a você) para que pudéssemos raspar um personagem e terminar com esse. Ainda estou grato por esse dia divertido, felicidades!
GitaarLAB
1
Por favor mencione que ye as mvariáveis ​​devem ser inteiras e não string! Isso causa cálculos errados, por exemplo, para fevereiro, retorna 30. Eu tive que usar a parseInt()função para fazê-la funcionar.
vez disso
21

Meu colega encontrou o seguinte, que pode ser uma solução mais fácil

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

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

brisa
fonte
2
Nigel modificou isso para uma solução ainda mais concisa. Veja o post dele.
orad 8/12/12
O mês é baseado em zero, ou seja, Jan = 0. O mesmo que getMonth ().
Moos
16

Uma leve modificação na solução fornecida pelo lebreeze :

function daysInMonth(iMonth, iYear)
{
    return new Date(iYear, iMonth, 0).getDate();
}
Nigel
fonte
Isso deve ser return new Date(iYear, 1 + iMonth, 0).getDate();equivalente à solução do @ lebreeze.
Moos
6

Recentemente, tive que fazer algo semelhante, foi o que descobri:

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

Passe-o em uma data e retornará uma data definida para o início do mês ou para o final do mês.

A begninngOfMonthfunção é bastante autoexplicativa, mas o que está acontecendo na endOfMonthfunção é que eu estou incrementando o mês para o próximo mês e depois usando setDate(0)para reverter o dia para o último dia do mês anterior, que faz parte do especificação setDate:

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

Em seguida, defino a hora / minutos / segundos para o final do dia, para que, se você estiver usando algum tipo de API que esteja esperando um período, possa capturar a totalidade desse último dia. Essa parte pode ir além do que a postagem original está solicitando, mas pode ajudar alguém a procurar uma solução semelhante.

Editar: você também pode percorrer uma milha extra e definir milissegundos setMilliseconds()se quiser ser mais preciso.

Eric
fonte
4

tente este.

lastDateofTheMonth = new Date(year, month, 0)

exemplo:

new Date(2012, 8, 0)

resultado:

Date {Fri Aug 31 2012 00:00:00 GMT+0900 (Tokyo Standard Time)}
artsylar
fonte
5
Lembre-se, porém, que os meses são baseados em zero, passando "8", pois o mês é realmente setembro, não agosto.
Steve J
3

Isso funciona para mim. Fornecerá o último dia do ano e mês especificado:

var d = new Date(2012,02,0);
var n = d.getDate();
alert(n);
Kreeverp
fonte
1
tenha cuidado com o 0 na frente do "2", ele será interpretado como octal.
Walfrat 04/04
1

Este funciona bem:

Date.prototype.setToLastDateInMonth = function () {

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

    return this;
}
Josue
fonte
1

Isso fornecerá o mês atual, primeiro e último dia.

Se você precisar alterar 'ano', remova d.getFullYear () e defina seu ano.

Se você precisar alterar 'month', remova d.getMonth () e defina seu ano.

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
fonte
1

Tente o seguinte:

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
fonte
1

A função abaixo fornece o último dia do mês:

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

Da mesma forma, podemos obter o primeiro dia do mês:

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

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

Sujay UN
fonte
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
fonte
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
fonte
0

defina o mês que você precisa namorar e, em seguida, defina o dia como zero, para que o mês comece na função de data de 1 a 31 e obtenha o último dia

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

ahmed samra
fonte
0

Aqui está uma resposta que economiza GMT e hora da data 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
fonte
0

Eu sei que é apenas uma questão de semântica, mas acabei usando-a desta forma.

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

Como as funções são resolvidas a partir do argumento interno, externamente, ele funciona da mesma maneira.

Você pode substituir o ano e o mês / ano pelos detalhes necessários, seja a partir da data atual. Ou um determinado mês / ano.

Rudi Strydom
fonte
0

Se você precisar do final exato do mês em milissegundos (por exemplo, em um carimbo de data / hora):

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
fonte