Calculer le dernier jour du mois en JavaScript

277

Si vous fournissez 0comme dayValueen Date.setFullYearvous obtenez le dernier jour du mois précédent:

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

Il y a une référence à ce comportement chez mozilla . Est-ce une fonctionnalité fiable pour tous les navigateurs ou dois-je envisager d'autres méthodes?

Ken
la source
Vous ne voulez pas dire le dernier jour du mois spécifié? Il y a 30 jours en novembre et 31 en octobre.
Chris Serra
16
Les mois sont basés sur zéro en javascript, donc le 11 est décembre
Greg
2
@TheCloudlessSky - essayez-le dans votre console ... (2008,11,0) est le zéro jour de décembre, et donc le dernier jour de novembre
Ken
@Ken - Ouais - je ne savais pas qu'il y avait un "0":) ... c'était trop tôt le matin.
TheCloudlessSky

Réponses:

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)

Les différences de sortie sont dues à des différences dans l' toString()implémentation, pas parce que les dates sont différentes.

Bien sûr, ce n'est pas parce que les navigateurs identifiés ci-dessus utilisent 0 comme dernier jour du mois précédent qu'ils continueront à le faire, ou que les navigateurs non répertoriés le feront, mais cela donne de la crédibilité à la croyance que cela devrait fonctionner. de la même manière dans tous les navigateurs.

Grant Wagner
la source
19
Cela semble fonctionner parfaitement bien. Par curiosité, qu'utilisez-vous pour exécuter le javascript sur tous ces moteurs? Vous avez tout configuré ou une sorte d'outil?
neonski
5
vous pouvez utiliser d.getDate () pour obtenir le jour réel.
rynop
35
"ce n'est pas parce que les navigateurs… utilisent 0 comme dernier jour du mois précédent qu'ils continueront à le faire". Oui, ils sont tenus de le faire par ECMA-262.
RobG
3
Veuillez noter que l'utilisation new Dateest tellement plus lente que les autres méthodes de calcul qu'elle n'apparaît même pas sur le tableau des performances
Gone Coding
4
Cela ne fonctionne pas pour moi sur Chrome 48.0.2564.116. Peut-être, cette façon a cessé d'être la «norme».
xarlymg89
77

J'utiliserais une date intermédiaire avec le premier jour du mois suivant et je retournerais la date du jour précédent:

int_d = new Date(2008, 11+1,1);
d = new Date(int_d - 1);
karlipoppins
la source
Selon la spécification ECMAScript , l'utilisation du constructeur "Date" comme vous l'avez souligné est valide. En suivant l'algorithme spécifié par la fonction "MakeDay", il devrait bien gérer le problème.
Pablo Cabrera
1
c'est la meilleure solution OMI. J'ai essayé la réponse acceptée mais elle a un bug lors de la récupération du dernier du mois en cours. Il renvoie la date du jour. Je ne sais pas pourquoi cela se produit cependant.
Gogol
1
Je ne peux pas reprocher le bug. Cela me donne une date correcte dans tous les navigateurs:today = new Date(); new Date(today.getFullYear(), today.getMonth()+1, 0).toString();
orad
Cela crée un objet Date pour le dernier jour du mois avec l'heure définie sur la dernière milliseconde (c'est-à-dire 23: 59: 59.999). Mieux vaut simplement utiliser la méthode dans l'OP et enregistrer l'étape supplémentaire et l'objet Date.
RobG
@RobG: je suis d'accord! bien que ma solution puisse être plus facile à comprendre, car la notion d'utiliser 0 pour le dernier jour du mois me semble un peu maladroite.
karlipoppins
72

Je trouve que c'est la meilleure solution pour moi. Laissez l'objet Date le calculer pour vous.

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

Régler le paramètre de jour sur 0 signifie un jour de moins que le premier jour du mois qui est le dernier jour du mois précédent.

orad
la source
1
C'est bon, j'ai remarqué que la réponse sélectionnée suggère la même chose. C'est le moyen le plus rapide et le plus fiable et fonctionne quel que soit le type de calendrier. Par exemple, si Date implémentait autre chose que le calendrier grégorien, cela fonctionnerait toujours. Voir intldate.codeplex.com pour un exemple d'implémentation non grégorienne de l'objet Date.
orad
1
@orad: Méfiez-vous de prétendre que quelque chose "est la plus rapide" car cette méthode est en fait considérablement plus lente que certaines alternatives. L'utilisation new Dateest tellement plus lente qu'elle n'apparaît même pas sur le tableau des performances
Gone Coding
@TrueBlueAussie OK. J'avais supposé que c'était plus rapide parce qu'il était natif. Mais tu as raison, ce n'est pas rapide. Merci de l'avoir testé. Quoi qu'il en soit, cette solution me convient le mieux car elle est concise et lisible et contrairement à toutes les autres solutions, elle n'est pas liée au calendrier grégorien.
orad
"contrairement à toutes les autres solutions n'est pas lié au calendrier grégorien" !!! Cet algorithme renvoie les mêmes valeurs que le mien pour les années 1-4000. jsfiddle.net/2973x9m3/3 Quelle plage de dates supplémentaires prétendez-vous que cela prendra en charge (qui serait utile)? :)
Gone Coding
1
Native JS Date utilise uniquement le calendrier grégorien. Mais vous pouvez vous en moquer avec une autre implémentation pour obtenir d'autres types de calendrier. Par exemple, voir IntlDate . Si vous avez un sélecteur de dates qui utilise des objets Date pour créer des vues mensuelles, il ne se soucie pas de l'implémentation de date (native ou simulée) qu'il utilise tant qu'il a la même interface. Ainsi, l'utilisation d'une interface partagée permet de basculer entre différents types de calendrier sans avoir à connaître le nombre de jours dans un mois sur chaque calendrier.
orad
25

En termes informatiques, new Date()et les regular expressionsolutions sont lentes! Si vous voulez une doublure ultra-rapide (et super-cryptique), essayez celle-ci (en supposant qu'elle mest au Jan=1format). Je continue d'essayer différentes modifications de code pour obtenir les meilleures performances.

Ma version la plus rapide actuelle :

Après avoir regardé cette question connexe Vérification de l'année bissextile en utilisant des opérateurs au niveau du bit (vitesse incroyable) et découvert ce que le nombre magique 25 et 15 représentait, j'ai trouvé cet hybride optimisé de réponses:

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

Compte tenu du décalage binaire, cela suppose évidemment que vos paramètres m& ysont tous deux des entiers, car le passage de nombres sous forme de chaînes entraînerait des résultats étranges.

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

Résultats JSPerf: http://jsperf.com/days-in-month-head-to-head/5

Pour une raison quelconque, (m+(m>>3)&1)est plus efficace que (5546>>m&1)sur presque tous les navigateurs.

La seule vraie compétition pour la vitesse vient de @GitaarLab, j'ai donc créé un JSPerf en tête à tête pour que nous puissions tester sur: http://jsperf.com/days-in-month-head-to-head/5


Cela fonctionne sur la base de ma réponse de l'année bissextile ici: javascript pour trouver l'année bissextile cette réponse ici Vérification de l'année bissextile en utilisant des opérateurs au niveau du bit (vitesse incroyable) ainsi que la logique binaire suivante.

Une leçon rapide en mois binaires:

Si vous interprétez l'index des mois souhaités (Jan = 1) en binaire, vous remarquerez que les mois avec 31 jours ont soit le bit 3 effacé et le bit 0 défini, soit le bit 3 réglé et le bit 0 effacé.

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

Cela signifie que vous pouvez décaler la valeur de 3 places avec >> 3, XOR les bits avec l'original ^ met voir si le résultat est 1ou 0 à la position 0 en utilisant & 1. Remarque: Il s'avère que +c'est légèrement plus rapide que XOR ( ^) et (m >> 3) + mdonne le même résultat dans le bit 0.

Résultats JSPerf : http://jsperf.com/days-in-month-perf-test/6

Fin du codage
la source
1
@GitaarLAB: Vous avez déjà obtenu une mention et ce n'était jamais exactement la même que la vôtre, comme vous le savez bien. La mise à jour incrémentielle des algorithmes de chacun n'est pas la même chose que "l'algo original". J'ai aussi mis beaucoup d'efforts dans cette réponse: P
Gone Coding
@TrueBlueAussie: Je voulais seulement pointer les futurs lecteurs vers notre trésor d'informations supplémentaires (j'ai lié nos deux réponses afin que quiconque s'en soucie ou souhaite y aller de nouveau puisse consulter notre historique des modifications pour voir quand nous avons fait quoi et pourquoi. ). Je me souviens toujours avec émotion de notre journée complète de compétition! :)La toute première version de réponse que j'ai publiée avait en effet un ensemble de supports inutiles, qui ont été supprimés (pour lesquels je vous ai crédité) afin que nous puissions raser un personnage et nous retrouver avec celui-ci. Je suis toujours reconnaissant pour cette journée amusante, cheers!
GitaarLAB
1
Veuillez le mentionner yet les mvariables doivent être des nombres entiers et non des chaînes! Cela provoque des calculs erronés par exemple pour février il en retourne 30. J'ai dû utiliser la parseInt()fonction pour le faire fonctionner.
au lieu de
21

Mon collègue est tombé sur ce qui pourrait être une solution plus facile

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

volé à http://snippets.dzone.com/posts/show/2099

lebreeze
la source
2
Nigel a modifié cela pour une solution encore plus concise. Voir son article.
2012
Le mois est basé sur zéro, c'est-à-dire que Jan = 0. Identique à getMonth ().
Moos
16

Une légère modification de la solution fournie par lebreeze :

function daysInMonth(iMonth, iYear)
{
    return new Date(iYear, iMonth, 0).getDate();
}
Nigel
la source
Cela devrait être return new Date(iYear, 1 + iMonth, 0).getDate();équivalent à la solution de @ lebreeze.
Moos
6

J'ai récemment dû faire quelque chose de similaire, voici ce que j'ai trouvé:

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

Passez-le dans une date et il renverra une date définie soit au début du mois, soit à la fin du mois.

La begninngOfMonthfonction est assez explicite, mais ce qui se passe dans la endOfMonthfonction est que j'incrémente le mois au mois suivant, puis que j'utilise setDate(0)pour faire reculer le jour jusqu'au dernier jour du mois précédent, qui fait partie de la spécification setDate:

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

J'ai ensuite réglé l'heure / minutes / secondes à la fin de la journée, de sorte que si vous utilisez une sorte d'API qui attend une plage de dates, vous pourrez capturer l'intégralité de ce dernier jour. Cette partie pourrait aller au-delà de ce que le message d'origine demande, mais cela pourrait aider quelqu'un d'autre à chercher une solution similaire.

Modifier: vous pouvez également aller plus loin et définir des millisecondes setMilliseconds()si vous voulez être très précis.

Eric
la source
4

essaye celui-là.

lastDateofTheMonth = new Date(year, month, 0)

exemple:

new Date(2012, 8, 0)

production:

Date {Fri Aug 31 2012 00:00:00 GMT+0900 (Tokyo Standard Time)}
artsylar
la source
5
Rappelez-vous, cependant, que les mois sont basés sur zéro, donc passer "8" car le mois est vraiment septembre, pas août.
Steve J
3

Cela fonctionne pour moi. Fournira le dernier jour de l'année et du mois donnés:

var d = new Date(2012,02,0);
var n = d.getDate();
alert(n);
Kreeverp
la source
1
attention au 0 devant le "2" il sera interprété comme octal.
Walfrat
1

Celui-ci fonctionne bien:

Date.prototype.setToLastDateInMonth = function () {

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

    return this;
}
Josue
la source
1

Cela vous donnera le mois en cours le premier et le dernier jour.

Si vous devez changer «année», supprimez d.getFullYear () et réglez votre année.

Si vous devez changer le «mois», supprimez d.getMonth () et réglez votre année.

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
la source
1

Essaye ça:

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
la source
1

La fonction ci-dessous donne le dernier jour du mois:

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

De même, nous pouvons obtenir le premier jour du mois:

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

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

Sujay UN
la source
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
la source
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
la source
0

définissez le mois dont vous avez besoin pour la date, puis réglez le jour sur zéro, afin que le mois commence par 1 à 31 dans la fonction de date, puis obtenez le dernier jour ^^

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

ahmed samra
la source
0

Voici une réponse qui conserve GMT et l'heure de la date initiale

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
la source
0

Je sais que c'est juste une question de sémantique, mais j'ai fini par l'utiliser sous cette forme.

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

Puisque les fonctions sont résolues de l'argument intérieur, vers l'extérieur, cela fonctionne de la même manière.

Vous pouvez alors simplement remplacer l'année et le mois / année par les détails requis, que ce soit à partir de la date actuelle. Ou un mois / une année en particulier.

Rudi Strydom
la source
0

Si vous avez besoin d'une fin de mois exacte en millisecondes (par exemple dans un horodatage):

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
la source