Je recherche le moyen le plus simple et le plus propre d'ajouter X mois à une date JavaScript.
Je préfère ne pas gérer le roulement de l'année ou devoir écrire ma propre fonction .
Y a-t-il quelque chose de intégré qui peut faire cela?
Je recherche le moyen le plus simple et le plus propre d'ajouter X mois à une date JavaScript.
Je préfère ne pas gérer le roulement de l'année ou devoir écrire ma propre fonction .
Y a-t-il quelque chose de intégré qui peut faire cela?
Réponses:
La fonction suivante ajoute des mois à une date en JavaScript ( source ). Il prend en compte les reports d'année et les durées de mois variables:
function addMonths(date, months) {
var d = date.getDate();
date.setMonth(date.getMonth() + +months);
if (date.getDate() != d) {
date.setDate(0);
}
return date;
}
// Add 12 months to 29 Feb 2016 -> 28 Feb 2017
console.log(addMonths(new Date(2016,1,29),12).toString());
// Subtract 1 month from 1 Jan 2017 -> 1 Dec 2016
console.log(addMonths(new Date(2017,0,1),-1).toString());
// Subtract 2 months from 31 Jan 2017 -> 30 Nov 2016
console.log(addMonths(new Date(2017,0,31),-2).toString());
// Add 2 months to 31 Dec 2016 -> 28 Feb 2017
console.log(addMonths(new Date(2016,11,31),2).toString());
La solution ci-dessus couvre le cas de bord de passer d'un mois avec un nombre de jours supérieur au mois de destination. par exemple.
Si le jour du mois change lors de la demande setMonth
, nous savons que nous avons débordé le mois suivant en raison d'une différence de durée. Dans ce cas, nous utilisons setDate(0)
pour revenir au dernier jour du mois précédent.
Remarque: cette version de cette réponse remplace une version antérieure (ci-dessous) qui ne gérait pas correctement les différentes durées de mois.
var x = 12; //or whatever offset
var CurrentDate = new Date();
console.log("Current date:", CurrentDate);
CurrentDate.setMonth(CurrentDate.getMonth() + x);
console.log("Date after " + x + " months:", CurrentDate);
J'utilise moment.js bibliothèque pour des manipulations de date-heure . Exemple de code à ajouter un mois:
var startDate = new Date(...);
var endDateMoment = moment(startDate); // moment(...) can also be used to parse dates in string format
endDateMoment.add(1, 'months');
Cette fonction gère les cas marginaux et est rapide:
function addMonthsUTC (date, count) {
if (date && count) {
var m, d = (date = new Date(+date)).getUTCDate()
date.setUTCMonth(date.getUTCMonth() + count, 1)
m = date.getUTCMonth()
date.setUTCDate(d)
if (date.getUTCMonth() !== m) date.setUTCDate(0)
}
return date
}
tester:
> d = new Date('2016-01-31T00:00:00Z');
Sat Jan 30 2016 18:00:00 GMT-0600 (CST)
> d = addMonthsUTC(d, 1);
Sun Feb 28 2016 18:00:00 GMT-0600 (CST)
> d = addMonthsUTC(d, 1);
Mon Mar 28 2016 18:00:00 GMT-0600 (CST)
> d.toISOString()
"2016-03-29T00:00:00.000Z"
Mise à jour pour les dates non UTC: (par A.Hatchkins)
function addMonths (date, count) {
if (date && count) {
var m, d = (date = new Date(+date)).getDate()
date.setMonth(date.getMonth() + count, 1)
m = date.getMonth()
date.setDate(d)
if (date.getMonth() !== m) date.setDate(0)
}
return date
}
tester:
> d = new Date(2016,0,31);
Sun Jan 31 2016 00:00:00 GMT-0600 (CST)
> d = addMonths(d, 1);
Mon Feb 29 2016 00:00:00 GMT-0600 (CST)
> d = addMonths(d, 1);
Tue Mar 29 2016 00:00:00 GMT-0600 (CST)
> d.toISOString()
"2016-03-29T06:00:00.000Z"
Étant donné qu'aucune de ces réponses ne tiendra compte de l'année en cours lorsque le mois change, vous pouvez en trouver une que j'ai faite ci-dessous qui devrait la gérer:
La méthode:
Date.prototype.addMonths = function (m) {
var d = new Date(this);
var years = Math.floor(m / 12);
var months = m - (years * 12);
if (years) d.setFullYear(d.getFullYear() + years);
if (months) d.setMonth(d.getMonth() + months);
return d;
}
Usage:
return new Date().addMonths(2);
Tiré des réponses @bmpsini et @Jazaret , mais sans étendre les prototypes: utiliser des fonctions simples ( Pourquoi étendre des objets natifs est-il une mauvaise pratique? ):
function isLeapYear(year) {
return (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0));
}
function getDaysInMonth(year, month) {
return [31, (isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
}
function addMonths(date, value) {
var d = new Date(date),
n = date.getDate();
d.setDate(1);
d.setMonth(d.getMonth() + value);
d.setDate(Math.min(n, getDaysInMonth(d.getFullYear(), d.getMonth())));
return d;
}
Utilise le:
var nextMonth = addMonths(new Date(), 1);
D'après les réponses ci-dessus, le seul qui gère les cas marginaux (bmpasini de la bibliothèque datejs) a un problème:
var date = new Date("03/31/2015");
var newDate = date.addMonths(1);
console.log(newDate);
// VM223:4 Thu Apr 30 2015 00:00:00 GMT+0200 (CEST)
OK mais:
newDate.toISOString()
//"2015-04-29T22:00:00.000Z"
pire :
var date = new Date("01/01/2015");
var newDate = date.addMonths(3);
console.log(newDate);
//VM208:4 Wed Apr 01 2015 00:00:00 GMT+0200 (CEST)
newDate.toISOString()
//"2015-03-31T22:00:00.000Z"
Cela est dû au fait que l'heure n'est pas réglée, revenant ainsi à 00:00:00, ce qui peut alors basculer vers la veille en raison de fuseaux horaires ou de changements de temps ou autre ...
Voici ma solution proposée, qui n'a pas ce problème, et est aussi, je pense, plus élégante en ce qu'elle ne repose pas sur des valeurs codées en dur.
/**
* @param isoDate {string} in ISO 8601 format e.g. 2015-12-31
* @param numberMonths {number} e.g. 1, 2, 3...
* @returns {string} in ISO 8601 format e.g. 2015-12-31
*/
function addMonths (isoDate, numberMonths) {
var dateObject = new Date(isoDate),
day = dateObject.getDate(); // returns day of the month number
// avoid date calculation errors
dateObject.setHours(20);
// add months and set date to last day of the correct month
dateObject.setMonth(dateObject.getMonth() + numberMonths + 1, 0);
// set day number to min of either the original one or last day of month
dateObject.setDate(Math.min(day, dateObject.getDate()));
return dateObject.toISOString().split('T')[0];
};
Unité testée avec succès avec:
function assertEqual(a,b) {
return a === b;
}
console.log(
assertEqual(addMonths('2015-01-01', 1), '2015-02-01'),
assertEqual(addMonths('2015-01-01', 2), '2015-03-01'),
assertEqual(addMonths('2015-01-01', 3), '2015-04-01'),
assertEqual(addMonths('2015-01-01', 4), '2015-05-01'),
assertEqual(addMonths('2015-01-15', 1), '2015-02-15'),
assertEqual(addMonths('2015-01-31', 1), '2015-02-28'),
assertEqual(addMonths('2016-01-31', 1), '2016-02-29'),
assertEqual(addMonths('2015-01-01', 11), '2015-12-01'),
assertEqual(addMonths('2015-01-01', 12), '2016-01-01'),
assertEqual(addMonths('2015-01-01', 24), '2017-01-01'),
assertEqual(addMonths('2015-02-28', 12), '2016-02-28'),
assertEqual(addMonths('2015-03-01', 12), '2016-03-01'),
assertEqual(addMonths('2016-02-29', 12), '2017-02-28')
);
Comme la plupart des réponses mis en évidence, nous pourrions utiliser setMonth () méthode avec getMonth () méthode pour ajouter un nombre spécifique de mois à une date donnée.
Exemple: (comme mentionné par @ChadD dans sa réponse.)
var x = 12; //or whatever offset var CurrentDate = new Date(); CurrentDate.setMonth(CurrentDate.getMonth() + x);
Mais nous devons utiliser cette solution avec soin car nous aurons des problèmes avec les boîtiers de bord.
Pour gérer les cas marginaux, la réponse donnée dans le lien suivant est utile.
https://stackoverflow.com/a/13633692/3668866
Solution simple: 2678400000
est de 31 jours en millisecondes
var oneMonthFromNow = new Date((+new Date) + 2678400000);
Mettre à jour:
Utilisez ces données pour créer notre propre fonction:
2678400000
- 31 jours2592000000
- 30 jours2505600000
- 29 jours2419200000
- 28 joursJuste pour ajouter à la réponse acceptée et aux commentaires.
var x = 12; //or whatever offset
var CurrentDate = new Date();
//For the very rare cases like the end of a month
//eg. May 30th - 3 months will give you March instead of February
var date = CurrentDate.getDate();
CurrentDate.setDate(1);
CurrentDate.setMonth(CurrentDate.getMonth()+X);
CurrentDate.setDate(date);
J'ai écrit cette solution alternative qui fonctionne bien pour moi. Il est utile lorsque vous souhaitez calculer la fin d'un contrat. Par exemple, début = 2016-01-15, mois = 6, fin = 2016-7-14 (c'est-à-dire dernier jour - 1):
<script>
function daysInMonth(year, month)
{
return new Date(year, month + 1, 0).getDate();
}
function addMonths(date, months)
{
var target_month = date.getMonth() + months;
var year = date.getFullYear() + parseInt(target_month / 12);
var month = target_month % 12;
var day = date.getDate();
var last_day = daysInMonth(year, month);
if (day > last_day)
{
day = last_day;
}
var new_date = new Date(year, month, day);
return new_date;
}
var endDate = addMonths(startDate, months);
</script>
Exemples:
addMonths(new Date("2016-01-01"), 1); // 2016-01-31
addMonths(new Date("2016-01-01"), 2); // 2016-02-29 (2016 is a leap year)
addMonths(new Date("2016-01-01"), 13); // 2017-01-31
addMonths(new Date("2016-01-01"), 14); // 2017-02-28
Voici un exemple de calcul d'une date future basée sur la saisie de la date (membershipssignup_date) + mois ajoutés (membershipsmonths) via les champs du formulaire.
Le champ membershipsmonths a une valeur par défaut de 0
Lien de déclenchement (peut être un événement onchange attaché au champ de terme d'adhésion):
<a href="#" onclick="calculateMshipExp()"; return false;">Calculate Expiry Date</a>
function calculateMshipExp() {
var calcval = null;
var start_date = document.getElementById("membershipssignup_date").value;
var term = document.getElementById("membershipsmonths").value; // Is text value
var set_start = start_date.split('/');
var day = set_start[0];
var month = (set_start[1] - 1); // January is 0 so August (8th month) is 7
var year = set_start[2];
var datetime = new Date(year, month, day);
var newmonth = (month + parseInt(term)); // Must convert term to integer
var newdate = datetime.setMonth(newmonth);
newdate = new Date(newdate);
//alert(newdate);
day = newdate.getDate();
month = newdate.getMonth() + 1;
year = newdate.getFullYear();
// This is British date format. See below for US.
calcval = (((day <= 9) ? "0" + day : day) + "/" + ((month <= 9) ? "0" + month : month) + "/" + year);
// mm/dd/yyyy
calcval = (((month <= 9) ? "0" + month : month) + "/" + ((day <= 9) ? "0" + day : day) + "/" + year);
// Displays the new date in a <span id="memexp">[Date]</span> // Note: Must contain a value to replace eg. [Date]
document.getElementById("memexp").firstChild.data = calcval;
// Stores the new date in a <input type="hidden" id="membershipsexpiry_date" value="" name="membershipsexpiry_date"> for submission to database table
document.getElementById("membershipsexpiry_date").value = calcval;
}
Comme le démontrent de nombreuses réponses complexes et laides présentées, les dates et les heures peuvent être un cauchemar pour les programmeurs utilisant n'importe quel langage. Mon approche consiste à convertir les dates et les valeurs «delta t» en Epoch Time (en ms), effectuer n'importe quelle arithmétique, puis reconvertir en «temps humain».
// Given a number of days, return a Date object
// that many days in the future.
function getFutureDate( days ) {
// Convert 'days' to milliseconds
var millies = 1000 * 60 * 60 * 24 * days;
// Get the current date/time
var todaysDate = new Date();
// Get 'todaysDate' as Epoch Time, then add 'days' number of mSecs to it
var futureMillies = todaysDate.getTime() + millies;
// Use the Epoch time of the targeted future date to create
// a new Date object, and then return it.
return new Date( futureMillies );
}
// Use case: get a Date that's 60 days from now.
var twoMonthsOut = getFutureDate( 60 );
Cela a été écrit pour un cas d'utilisation légèrement différent, mais vous devriez pouvoir l'adapter facilement aux tâches connexes.
EDIT: Source complète ici !
Tout cela semble beaucoup trop compliqué et je suppose que cela entre dans un débat sur ce que signifie exactement "un mois". Cela signifie-t-il 30 jours? Cela signifie-t-il du 1er au 1er? Du dernier jour au dernier jour?
Si c'est le cas, l'ajout d'un mois au 27 février vous amène au 27 mars, mais l'ajout d'un mois au 28 février vous amène au 31 mars (sauf les années bissextiles, où cela vous mène au 28 mars). Ensuite, en soustrayant un mois du 30 mars, vous obtenez ... 27 février? Qui sait...
Pour ceux qui recherchent une solution simple, ajoutez simplement des millisecondes et terminez.
function getDatePlusDays(dt, days) {
return new Date(dt.getTime() + (days * 86400000));
}
ou
Date.prototype.addDays = function(days) {
this = new Date(this.getTime() + (days * 86400000));
};
d.setMonth(d.getMonth()+1)
? Ce n'est donc même pas l'idée la plus simple.
addDateMonate : function( pDatum, pAnzahlMonate )
{
if ( pDatum === undefined )
{
return undefined;
}
if ( pAnzahlMonate === undefined )
{
return pDatum;
}
var vv = new Date();
var jahr = pDatum.getFullYear();
var monat = pDatum.getMonth() + 1;
var tag = pDatum.getDate();
var add_monate_total = Math.abs( Number( pAnzahlMonate ) );
var add_jahre = Number( Math.floor( add_monate_total / 12.0 ) );
var add_monate_rest = Number( add_monate_total - ( add_jahre * 12.0 ) );
if ( Number( pAnzahlMonate ) > 0 )
{
jahr += add_jahre;
monat += add_monate_rest;
if ( monat > 12 )
{
jahr += 1;
monat -= 12;
}
}
else if ( Number( pAnzahlMonate ) < 0 )
{
jahr -= add_jahre;
monat -= add_monate_rest;
if ( monat <= 0 )
{
jahr = jahr - 1;
monat = 12 + monat;
}
}
if ( ( Number( monat ) === 2 ) && ( Number( tag ) === 29 ) )
{
if ( ( ( Number( jahr ) % 400 ) === 0 ) || ( ( Number( jahr ) % 100 ) > 0 ) && ( ( Number( jahr ) % 4 ) === 0 ) )
{
tag = 29;
}
else
{
tag = 28;
}
}
return new Date( jahr, monat - 1, tag );
}
testAddMonate : function( pDatum , pAnzahlMonate )
{
var datum_js = fkDatum.getDateAusTTMMJJJJ( pDatum );
var ergebnis = fkDatum.addDateMonate( datum_js, pAnzahlMonate );
app.log( "addDateMonate( \"" + pDatum + "\", " + pAnzahlMonate + " ) = \"" + fkDatum.getStringAusDate( ergebnis ) + "\"" );
},
test1 : function()
{
app.testAddMonate( "15.06.2010", 10 );
app.testAddMonate( "15.06.2010", -10 );
app.testAddMonate( "15.06.2010", 37 );
app.testAddMonate( "15.06.2010", -37 );
app.testAddMonate( "15.06.2010", 1234 );
app.testAddMonate( "15.06.2010", -1234 );
app.testAddMonate( "15.06.2010", 5620 );
app.testAddMonate( "15.06.2010", -5120 );
}
Parfois utile pour créer une date par un opérateur comme dans les paramètres BIRT
J'ai fait 1 mois de retour avec:
new Date(new Date().setMonth(new Date().getMonth()-1));