web-dev-qa-db-fra.com

Fonction JavaScript pour ajouter X mois à une date

Je cherche 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 d'intégré qui peut faire ça?

171
ChadD

Je pense que cela devrait le faire:

var x = 12; //or whatever offset
var CurrentDate = new Date();
CurrentDate.setMonth(CurrentDate.getMonth() + x);

Je crois que cela devrait automatiquement gérer le passage à l’année appropriée et au mois approprié.

l'essayer

238
ChadD

J'utilise moment.js bibliothèque pour manipulations 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');
51
anre

Cette fonction gère les cas Edge 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"
19
aMarCruz

Considérant qu'aucune de ces réponses ne tiendra compte de l'année en cours lorsque le mois change, vous pouvez en trouver une 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);
13
Control Freak

Tiré de @bmpsini et @Jazaret réponses, mais sans extension de prototypes: utilisation de fonctions simples ( Pourquoi l'extension d'objets natifs est-elle 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);
6
Miquel
d = new Date();

alert(d.getMonth()+1);

Les mois ayant un index basé sur 0, il convient d'alerter (4) qui vaut 5 (peut);

2
Ben

Comme la plupart des réponses mises en évidence, nous pourrions utiliser la méthode setMonth () avec la méthode getMonth () 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 devrions utiliser cette solution avec précaution car nous aurons des problèmes avec les cas Edge. 

Pour traiter les cas Edge, la réponse donnée dans le lien suivant est utile. 

https://stackoverflow.com/a/13633692/3668866

2
Sampath Dilhan

Juste 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);
2
iamjt

Parmi les réponses ci-dessus, le seul qui gère les cas Edge (la bibliothèque de bmpasini from 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'a pas été réglée, revenant ainsi à 00:00:00, qui peut ensuite glisser au jour précédent en raison d'un fuseau horaire ou de modifications permettant de gagner du temps, etc.

Voici la solution proposée, qui ne pose pas ce problème, mais qui est aussi, à mon avis, plus élégante en ce sens 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')
);
2
pansay

Solution simple: 2678400000 correspond à 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 jours
  • 2592000000 - 30 jours
  • 2505600000 - 29 jours
  • 2419200000 - 28 jours
2
dr.dimitru

Tout cela semble bien trop compliqué et j'imagine que le débat sur ce que signifie exactement «un mois» signifie. Est-ce que cela signifie 30 jours? Est-ce que cela signifie du 1er au 1er? Du dernier jour au dernier jour?

Dans ce dernier cas, ajouter un mois au 27 février vous amènera au 27 mars, mais ajouter un mois au 28 février vous amènera au 31 mars (sauf les années bissextiles, où vous obtiendrez le 28 mars). En soustrayant ensuite un mois du 30 mars, vous obtenez ... le 27 février? Qui sait...

Pour ceux qui recherchent une solution simple, il suffit d’ajouter des millisecondes et d’être terminé.

function getDatePlusDays(dt, days) {
  return new Date(dt.getTime() + (days * 86400000));
}

ou

Date.prototype.addDays = function(days) {
  this = new Date(this.getTime() + (days * 86400000));
};
0
jdforsythe

Voici un exemple de calcul d'une date future en fonction de la date entrée (membershipssignup_date) + des mois ajoutés (membershipsmonths) via des champs de 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 du terme d'appartenance):

<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;
}
0
John G

Comme le démontrent nombre des réponses compliquées et laides présentées, Dates et heures peuvent être un cauchemar pour les programmeurs de n’importe quel langage. Mon approche consiste à convertir les dates et les valeurs «delta t» en Epoch Time (en ms), à effectuer des opérations arithmétiques, puis à reconvertir en «heure humaine».

// 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 à des tâches connexes.

EDIT: Source complète ici !

0
Dan Ahlquist

J'ai écrit cette solution alternative qui me convient parfaitement. C'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;
    year = date.getFullYear() + parseInt(target_month / 12);
    month = target_month % 12;
    day = date.getDate();
    last_day = daysInMonth(year, month);
    if (day > last_day)
    {
        day = last_day;
    }
    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
0
David Ragazzi