Javascript - obtenir un tableau de dates entre 2 dates

155
var range = getDates(new Date(), new Date().addDays(7));

Je voudrais que "range" soit un tableau d'objets de date, un pour chaque jour entre les deux dates.

L'astuce est qu'il doit également gérer les limites des mois et des années.

Scott Klarenbach
la source

Réponses:

171
Date.prototype.addDays = function(days) {
    var date = new Date(this.valueOf());
    date.setDate(date.getDate() + days);
    return date;
}

function getDates(startDate, stopDate) {
    var dateArray = new Array();
    var currentDate = startDate;
    while (currentDate <= stopDate) {
        dateArray.push(new Date (currentDate));
        currentDate = currentDate.addDays(1);
    }
    return dateArray;
}

Voici une démo fonctionnelle http://jsfiddle.net/jfhartsock/cM3ZU/

John Hartsock
la source
2
Merci John. J'ai surtout utilisé le vôtre, mais vous avez un bogue byRef, dans ce currentDate ne peut pas être poussé sur le tableau ou vous vous retrouverez avec un tableau de n éléments, tous comme date de dernière. Le changer en currentDate = new Date (currentDate) fonctionne.
Scott Klarenbach
c'est bien pour la date future, mais lorsque je travaille sur une date passée comme 30 jours avant, où dois-je changer le code ci-dessus pour obtenir uniquement la date et non l'heure.
vaibhav kulkarni
@vaibhavkulkarni Vous pouvez simplement inverser le prototype addays () et modifier la boucle while. De plus, les commentaires ne sont pas le lieu pour lancer une nouvelle question.
John Hartsock
Devrions-nous mieux retirer le temps de startDateet endDate? Parce que si l startDate'heure est postérieure à l stopDate' heure, elle ne sera pas incluse stopDatedans le résultat, non?
Hp93 du
@ Hp93 Je ne sais pas exactement de quoi vous parlez. Si vous exécutez le violon que j'ai fourni, vous verrez qu'il couvre cette situation.
John Hartsock
58

Essayez ceci, n'oubliez pas d'inclure moment js,

function getDates(startDate, stopDate) {
    var dateArray = [];
    var currentDate = moment(startDate);
    var stopDate = moment(stopDate);
    while (currentDate <= stopDate) {
        dateArray.push( moment(currentDate).format('YYYY-MM-DD') )
        currentDate = moment(currentDate).add(1, 'days');
    }
    return dateArray;
}
Mohammed Safeer
la source
Juste une petite amélioration: la notation abrégée pour la création de tableaux est recommandée var dateArray = [];Détails ici
Adrian Moisa
C'est la nouvelle façon de définir les tableaux, et je suppose qu'elle est plus courte / plus propre.
Mohammed Safeer
1
Correctif important : var currentDate = moment(startDate);si vous utilisez cette méthode deux fois aux mêmes dates moment.js, vous serez surpris de savoir pourquoi cela fonctionne la première fois. Cela se produit parce que javascripts passe des objets par référence, de sorte que la fonction finit par utiliser la startDate deux fois (qui est déjà mutée). La mise à jour du correctif ci-dessus garantit que vous travaillez avec de nouveaux et uniques objets moment js dans la portée de la fonction. Vérifiez ce violon
Adrian Moisa
53

J'ai regardé tous ceux ci-dessus. J'ai fini par m'écrire. Vous n'avez pas besoin de momentjs pour cela . Une boucle for native est suffisante et a plus de sens car une boucle for existe pour compter les valeurs dans une plage.

Bon mot:

var getDaysArray = function(s,e) {for(var a=[],d=new Date(s);d<=e;d.setDate(d.getDate()+1)){ a.push(new Date(d));}return a;};

Version longue

var getDaysArray = function(start, end) {
    for(var arr=[],dt=new Date(start); dt<=end; dt.setDate(dt.getDate()+1)){
        arr.push(new Date(dt));
    }
    return arr;
};

Liste des dates entre:

var daylist = getDaysArray(new Date("2018-05-01"),new Date("2018-07-01"));
daylist.map((v)=>v.toISOString().slice(0,10)).join("")
/*
Output: 
    "2018-05-01
    2018-05-02
    2018-05-03
    ...
    2018-06-30
    2018-07-01"
*/

Jours entre une date passée et maintenant:

var daylist = getDaysArray(new Date("2018-05-01"),new Date());
daylist.map((v)=>v.toISOString().slice(0,10)).join("")
enesn
la source
Que faire si vous souhaitez récupérer tous les jours spécifiés getDaysArray? Pas les jours entre eux.
Jonjie
Merci! exactement ce dont j'avais besoin sans dépendances. :)
mpsyp
2
cette fonction manipule la date d'entrée source. :) Je l'ai testé.
Hamed Taheri
4
@ HamedTaheri — oui, mais cela peut être corrigé en attribuant une copie de start à dt plutôt que de démarrer lui-même, par exemple for (var arr=[], dt=new Date(start), ...). ;-)
RobG
fonctionne bien, mais dommage qu'une boucle for (;;) n'est pas aussi lisible pour la maintenance logicielle lorsque vous travaillez avec beaucoup d'autres personnes.
Victor
27

J'utilise moment.js et Twix.js, ils fournissent un très bon support pour la manipulation de la date et de l'heure

var itr = moment.twix(new Date('2012-01-15'),new Date('2012-01-20')).iterate("days");
var range=[];
while(itr.hasNext()){
    range.push(itr.next().toDate())
}
console.log(range);

J'ai ceci en cours d'exécution sur http://jsfiddle.net/Lkzg1bxb/

Ahmed Aswani
la source
J'ai téléchargé tous les fichiers associés, mais il affiche toujours l'erreur TypeError: moment.twix n'est pas une fonction
vaibhav kulkarni
Vous devrez peut-être inclure les bibliothèques. Dans nodejs ça va comme, var moment = require ('moment'); require ('twix');
Dr Bala Soundararaj
18
var boxingDay = new Date("12/26/2010");
var nextWeek  = boxingDay*1 + 7*24*3600*1000;

function getDates( d1, d2 ){
  var oneDay = 24*3600*1000;
  for (var d=[],ms=d1*1,last=d2*1;ms<last;ms+=oneDay){
    d.push( new Date(ms) );
  }
  return d;
}

getDates( boxingDay, nextWeek ).join("\n");
// Sun Dec 26 2010 00:00:00 GMT-0700 (Mountain Standard Time)
// Mon Dec 27 2010 00:00:00 GMT-0700 (Mountain Standard Time)
// Tue Dec 28 2010 00:00:00 GMT-0700 (Mountain Standard Time)
// Wed Dec 29 2010 00:00:00 GMT-0700 (Mountain Standard Time)
// Thu Dec 30 2010 00:00:00 GMT-0700 (Mountain Standard Time)
// Fri Dec 31 2010 00:00:00 GMT-0700 (Mountain Standard Time)
// Sat Jan 01 2011 00:00:00 GMT-0700 (Mountain Standard Time)
Phrogz
la source
3
Pour être sûr, contrairement à ce qui précède, vous devez généralement choisir une heure au milieu de la journée pour éviter de légères variations dues à l'heure d'été.
Phrogz
J'aimerais que vous ajoutiez également un changement de milieu de journée au code.
poulets
15
function (startDate, endDate, addFn, interval) {

 addFn = addFn || Date.prototype.addDays;
 interval = interval || 1;

 var retVal = [];
 var current = new Date(startDate);

 while (current <= endDate) {
  retVal.push(new Date(current));
  current = addFn.call(current, interval);
 }

 return retVal;

}
Scott Klarenbach
la source
1
Cela se bloquerait si vous fournissiez des dates dans un ordre incorrect
pie6k
11

Si vous utilisez moment, vous pouvez utiliser leur "plugin officiel" pour les plages moment-rangeet cela devient trivial.

exemple de nœud de plage de moment:

const Moment = require('moment');
const MomentRange = require('moment-range');
const moment = MomentRange.extendMoment(Moment);

const start = new Date("11/30/2018"), end = new Date("09/30/2019")
const range = moment.range(moment(start), moment(end));

console.log(Array.from(range.by('day')))

exemple de navigateur de moment-intervalle:

window['moment-range'].extendMoment(moment);

const start = new Date("11/30/2018"), end = new Date("09/30/2019")
const range = moment.range(moment(start), moment(end));

console.log(Array.from(range.by('day')))
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-range/4.0.1/moment-range.js"></script>

exemple de date fns:

Si vous utilisez, date-fnsalors eachDayc'est votre ami et vous obtenez de loin la réponse la plus courte et la plus concise:

console.log(dateFns.eachDay(
  new Date(2018, 11, 30),
  new Date(2019, 30, 09)
))
<script src="https://cdnjs.cloudflare.com/ajax/libs/date-fns/1.29.0/date_fns.min.js"></script>

Akrion
la source
8

Je viens de tomber sur cette question, le moyen le plus simple de le faire est d'utiliser le moment:

Vous devez d'abord installer le moment et la plage de moment:

const Moment = require('moment');
const MomentRange = require('moment-range');
const moment = MomentRange.extendMoment(Moment);

const start = moment()
const end = moment().add(2, 'months')
const range = moment.range(start, end)
const arrayOfDates = Array.from(range.by('days'))
console.log(arrayOfDates)
Irfy
la source
6

J'utilise la solution @Mohammed Safeer depuis un moment et j'ai apporté quelques améliorations. L'utilisation de dates formatées est une mauvaise pratique lorsque vous travaillez dans vos contrôleurs. moment().format()ne doit être utilisé qu'à des fins d'affichage dans les vues. Souvenez-vous également que cela moment().clone()garantit la séparation des paramètres d'entrée, ce qui signifie que les dates d'entrée ne sont pas modifiées. Je vous encourage fortement à utiliser moment.js lorsque vous travaillez avec des dates.

Usage:

  • Fournir des dates moment.js comme valeurs pour startDate, endDateparamètres
  • intervalLe paramètre est facultatif et est défini par défaut sur «jours». Utilisez les intervalles supportés par la .add()méthode (moment.js). Plus de détails ici
  • totalparamètre est utile lors de la spécification des intervalles en minutes. La valeur par défaut est 1.

Invoquer:

var startDate = moment(),
    endDate = moment().add(1, 'days');

getDatesRangeArray(startDate, endDate, 'minutes', 30);

Fonction:

var getDatesRangeArray = function (startDate, endDate, interval, total) {
    var config = {
            interval: interval || 'days',
            total: total || 1
        },
        dateArray = [],
        currentDate = startDate.clone();

    while (currentDate < endDate) {
        dateArray.push(currentDate);
        currentDate = currentDate.clone().add(config.total, config.interval);
    }

    return dateArray;
};
Adrian Moisa
la source
6

En utilisant ES6, vous avez Array.from, ce qui signifie que vous pouvez écrire une fonction vraiment élégante, qui permet des intervalles dynamiques (heures, jours, mois).

function getDates(startDate, endDate, interval) {
const duration = endDate - startDate;
const steps = duration / interval;
return Array.from({length: steps+1}, (v,i) => new Date(startDate.valueOf() + (interval * i)));
}
const startDate = new Date(2017,12,30);
const endDate = new Date(2018,1,3);
const dayInterval = 1000 * 60 * 60 * 24; // 1 day
const halfDayInterval = 1000 * 60 * 60 * 12; // 1/2 day

console.log("Days", getDates(startDate, endDate, dayInterval));
console.log("Half Days", getDates(startDate, endDate, halfDayInterval));

digiguru
la source
2
«Élégant» dépend de votre point de vue. new Date(2017,12,30)est le 30 janvier 2018, pour moi, la plage de dates commence le 29 janvier 2018. Tous les jours ne durent pas 8,64e7 ms (24 h) lorsque l'heure d'été est observée. ;-)
RobG
5

Je travaillais récemment avec moment.js, la suite a fait l'affaire.

function getDateRange(startDate, endDate, dateFormat) {
        var dates = [],
            end = moment(endDate),
            diff = endDate.diff(startDate, 'days');

        if(!startDate.isValid() || !endDate.isValid() || diff <= 0) {
            return;
        }

        for(var i = 0; i < diff; i++) {
            dates.push(end.subtract(1,'d').format(dateFormat));
        }

        return dates;
    };
    console.log(getDateRange(startDate, endDate, dateFormat));

Le résultat serait:

["09/03/2015", "10/03/2015", "11/03/2015", "12/03/2015", "13/03/2015", "14/03/2015", "15/03/2015", "16/03/2015", "17/03/2015", "18/03/2015"]
gor181
la source
3
var listDate = [];
var startDate ='2017-02-01';
var endDate = '2017-02-10';
var dateMove = new Date(startDate);
var strDate = startDate;

while (strDate < endDate){
  var strDate = dateMove.toISOString().slice(0,10);
  listDate.push(strDate);
  dateMove.setDate(dateMove.getDate()+1);
};
console.log(listDate);

//["2017-02-01", "2017-02-02", "2017-02-03", "2017-02-04", "2017-02-05", "2017-02-06", "2017-02-07", "2017-02-08", "2017-02-09", "2017-02-10"]
Công Thắng
la source
1
Veuillez ajouter plus de description et / ou d'informations sur votre réponse et sur la façon dont elle résout le problème posé afin que les autres puissent facilement la comprendre sans demander de clarification
koceeng
Je trouve que cela saute le 31/03/2016 pour une raison quelconque!
woodhead92
1
Vous ne devriez pas avoir varavant strDatedans la boucle while!
Boris Yakubchik
2

d3js fournit de nombreuses fonctions pratiques et inclut d3.time pour des manipulations faciles de la date

https://github.com/d3/d3-time

Pour votre demande spécifique:

UTC

var range = d3.utcDay.range(new Date(), d3.utcDay.offset(new Date(), 7));

ou heure locale

var range = d3.timeDay.range(new Date(), d3.timeDay.offset(new Date(), 7));

plage sera un tableau d'objets de date correspondant à la première valeur possible pour chaque jour

vous pouvez changer timeDay en timeHour, timeMonth etc. pour les mêmes résultats à des intervalles différents

Russell Thompson
la source
2

Voici une ligne unique qui ne nécessite aucune bibliothèque au cas où vous ne voudriez pas créer une autre fonction. Remplacez simplement startDate (à deux endroits) et endDate (qui sont des objets de date js) par vos variables ou valeurs de date. Bien sûr, vous pouvez l'envelopper dans une fonction si vous préférez

Array(Math.floor((endDate - startDate) / 86400000) + 1).fill().map((_, idx) => (new Date(startDate.getTime() + idx * 86400000)))
ti994a
la source
cela ne prend pas en compte les changements d'heure d'été / standard .. certains jours sont plus longs et d'autres plus courts
Mike
2

J'utilise cette fonction

function getDatesRange(startDate, stopDate) {
    const ONE_DAY = 24*3600*1000;
    var days= [];
    var currentDate = new Date(startDate);
    while (currentDate <= stopDate) {
        days.push(new Date (currentDate));
        currentDate = currentDate - 1 + 1 + ONE_DAY;
    }
    return days;
}
IdontCareAboutReputationPoints
la source
2

J'utilise une simple boucle while pour calculer les dates intermédiaires

var start = new Date("01/05/2017");
var end = new Date("06/30/2017");
var newend = end.setDate(end.getDate()+1);
end = new Date(newend);
while(start < end){
   console.log(new Date(start).getTime() / 1000); // unix timestamp format
   console.log(start); // ISO Date format          
   var newDate = start.setDate(start.getDate() + 1);
   start = new Date(newDate);
}

KARTHIKEYAN.A
la source
1

Remarque: je sais que c'est légèrement différent de la solution demandée, mais je pense que beaucoup la trouveront utile.

Si vous voulez trouver chaque intervalle "x" (jours, mois, années, etc ...) entre deux dates, moment.js et les packages d'extension moment-range activent cette fonctionnalité.

Par exemple, pour trouver chaque 30e jour entre deux dates :

window['moment-range'].extendMoment(moment);

var dateString = "2018-05-12 17:32:34.874-08";
var start  = new Date(dateString);
var end    = new Date();
var range1 = moment.range(start, end);
var arrayOfIntervalDates = Array.from(range1.by('day', { step: 30 }));

arrayOfIntervalDates.map(function(intervalDate){
  console.log(intervalDate.format('YY-M-DD'))
});
Calcul
la source
1
  1. Générez un tableau d'années:

    const DAYS = () => {
     const days = []
     const dateStart = moment()
     const dateEnd = moment().add(30, days')
     while (dateEnd.diff(dateStart, days') >= 0) {
      days.push(dateStart.format(‘D'))
      dateStart.add(1, days')
     }
     return days
    }
    console.log(DAYS())
  2. Générez un tableau pour un mois:

            const MONTHS = () => {
             const months = []
             const dateStart = moment()
             const dateEnd = moment().add(12, month')
             while (dateEnd.diff(dateStart, months') >= 0) {
              months.push(dateStart.format(‘M'))
              dateStart.add(1, month')
             }
             return months
            }
            console.log(MONTHS())
  3. Générez des tableaux pendant des jours:

            const DAYS = () => {
             const days = []
             const dateStart = moment()
             const dateEnd = moment().add(30, days')
             while (dateEnd.diff(dateStart, days') >= 0) {
              days.push(dateStart.format(‘D'))
              dateStart.add(1, days')
             }
             return days
            }
            console.log(DAYS())
elnaz nasiri
la source
1

Vous pouvez le faire facilement en utilisant momentJS

Ajoutez du moment à vos dépendances

npm i moment

Puis importez-le dans votre fichier

var moment = require("moment");

Ensuite, utilisez le code suivant pour obtenir la liste de toutes les dates entre deux dates

let dates = [];
let currDate = moment.utc(new Date("06/30/2019")).startOf("day");
let lastDate = moment.utc(new Date("07/30/2019")).startOf("day");

do {
 dates.push(currDate.clone().toDate());
} while (currDate.add(1, "days").diff(lastDate) < 0);
dates.push(currDate.clone().toDate());

console.log(dates);
Nitesh Malviya
la source
0

Cela peut aider quelqu'un,

Vous pouvez obtenir la sortie de ligne à partir de cela et formater l'objet row_date comme vous le souhaitez.

var from_date = '2016-01-01';
var to_date = '2016-02-20';

var dates = getDates(from_date, to_date);

console.log(dates);

function getDates(from_date, to_date) {
  var current_date = new Date(from_date);
  var end_date     = new Date(to_date);

  var getTimeDiff = Math.abs(current_date.getTime() - end_date.getTime());
  var date_range = Math.ceil(getTimeDiff / (1000 * 3600 * 24)) + 1 ;

  var weekday = ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"];
  var months = ["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"];
  var dates = new Array();

  for (var i = 0; i <= date_range; i++) {
     var getDate, getMonth = '';

     if(current_date.getDate() < 10) { getDate = ('0'+ current_date.getDate());}
     else{getDate = current_date.getDate();}

    if(current_date.getMonth() < 9) { getMonth = ('0'+ (current_date.getMonth()+1));}
    else{getMonth = current_date.getMonth();}

    var row_date = {day: getDate, month: getMonth, year: current_date.getFullYear()};
    var fmt_date = {weekDay: weekday[current_date.getDay()], date: getDate, month: months[current_date.getMonth()]};
    var is_weekend = false;
    if (current_date.getDay() == 0 || current_date.getDay() == 6) {
        is_weekend = true;
    }
    dates.push({row_date: row_date, fmt_date: fmt_date, is_weekend: is_weekend});
    current_date.setDate(current_date.getDate() + 1);
 }
 return dates;
}

https://gist.github.com/pranid/3c78f36253cbbc6a41a859c5d718f362.js

Praneeth Nidarshan
la source
0

Voici une méthode prédéfinie qui acceptera des dates ou des chaînes Moment ou un mélange comme entrées et générera un tableau de dates en tant que dates Moment. Si vous ne voulez pas de dates Moment comme sortie, modifiez ce que la map()méthode renvoie.

const moment = require('moment');

// ...

/**
 * @param {string|import('moment').Moment} start
 * @param {string|import('moment').Moment} end
 * @returns {import('moment').Moment[]}
 */
const getDateRange = (start, end) => {
  const s = moment.isMoment(start) ? start : moment(start);
  const e = moment.isMoment(end) ? end : moment(end);
  return [...Array(1 + e.diff(s, 'days')).keys()].map(n => moment(s).add(n, 'days'));
};
Gars
la source
0

@ la solution de softvar, mais avec l'option des dates de travail

/**
 * Returns array of working days between two dates.
 *
 * @param {string} startDate
 *   The start date in yyyy-mm-dd format.
 * @param {string} endDate
 *   The end date in yyyy-mm-dd format.
 * @param {boolean} onlyWorkingDays
 *   If true only working days are returned. Default: false
 *
 * @return {array}
 *   Array of dates in yyyy-mm-dd string format.
 */
function getDates(startDate, stopDate, onlyWorkingDays) {
  let doWd = typeof onlyWorkingDays ==='undefined' ? false : onlyWorkingDays;

  let dateArray = [];  
  let dayNr;
  let runDateObj = moment(startDate);  
  let stopDateObj = moment(stopDate);

  while (runDateObj <= stopDateObj) {
    dayNr = runDateObj.day();
    if (!doWd || (dayNr>0 && dayNr<6)) {
     dateArray.push(moment(runDateObj).format('YYYY-MM-DD'));  
    }

    runDateObj = moment(runDateObj).add(1, 'days');
  }
  return dateArray;
}
koosvdkolk
la source
0

Fonction:

  var dates = [],
      currentDate = startDate,
      addDays = function(days) {
        var date = new Date(this.valueOf());
        date.setDate(date.getDate() + days);
        return date;
      };
  while (currentDate <= endDate) {
    dates.push(currentDate);
    currentDate = addDays.call(currentDate, 1);
  }
  return dates;
};

Usage:

var dates = getDatesRange(new Date(2019,01,01), new Date(2019,01,25));                                                                                                           
dates.forEach(function(date) {
  console.log(date);
});

J'espère que ça vous aide

Nelson Dang
la source