Javascript: ottieni una serie di date tra 2 date


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

Vorrei che "intervallo" fosse una matrice di oggetti data, uno per ogni giorno tra le due date.

Il trucco è che dovrebbe gestire anche i limiti del mese e dell'anno.

Risposte:


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

Ecco una demo funzionale http://jsfiddle.net/jfhartsock/cM3ZU/


2
Grazie John Ho usato principalmente il tuo, ma hai un bug byRef, in quanto currentDate non può essere inserito nell'array o finirai con un array di n elementi, il tutto come ultima data. Modificandolo in currentDate = new Date (currentDate) funziona.
Scott Klarenbach,

questo va bene per la data futura, ma quando sto lavorando su una data passata come 30 giorni prima dove dovrei cambiare il codice sopra per ottenere solo la data e non l'ora.
vaibhav kulkarni,

@vaibhavkulkarni Puoi semplicemente invertire il prototipo addays () e modificare il ciclo while. Inoltre, i commenti non sono il posto giusto per iniziare una nuova domanda.
John Hartsock,

Dovremmo rimuovere meglio il tempo da startDatee endDate? Perché se startDateil tempo è più tardi del stopDatetempo, non includerà stopDatenel risultato, giusto?
Hp93,

@ Hp93 Non sono sicuro di cosa stia parlando. Se corri il violino che ti ho fornito, vedrai che copre quella situazione.
John Hartsock,

58

Prova questo, ricordati di includere 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;
}

Solo un piccolo miglioramento: si consiglia una notazione abbreviata per la creazione di array var dateArray = [];Dettagli qui
Adrian Moisa

È il nuovo modo di definire gli array e suppongo che sia più breve / più pulito.
Mohammed Safeer,

1
Correzione importante : var currentDate = moment(startDate);nel caso in cui tu stia usando questo metodo due volte nello stesso momento date.js sarai perplesso sul perché funzioni solo la prima volta. Ciò accade perché javascripts passa gli oggetti per riferimento, quindi la funzione finisce due volte con startDate (che è già mutato). L'applicazione di patch alla correzione di cui sopra garantisce che si stia utilizzando oggetti js momento nuovi e unici nell'ambito della funzione.
Dai

53

Ho guardato tutti quelli sopra. Ho finito per scrivere me stesso. Non hai bisogno di momentjs per questo . Un ciclo for nativo è sufficiente e ha più senso perché esiste un ciclo for per contare i valori in un intervallo.

Una fodera:

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

Versione lunga

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

Elencare le date tra:

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"
*/

Giorni da una data passata fino ad ora:

var daylist = getDaysArray(new Date("2018-05-01"),new Date());
daylist.map((v)=>v.toISOString().slice(0,10)).join("")

Cosa succede se si desidera recuperare tutti i giorni specificati getDaysArray? Non i giorni tra di esso.
Jonjie,

Grazie! esattamente ciò di cui avevo bisogno senza dipendenze. :)
mpsyp,

2
questa funzione modifica la data di input della fonte. :) L'ho provato.
Hamed Taheri,

4
@ HamedTaheri: sì, ma ciò può essere risolto assegnando una copia di start a dt anziché start stesso, ad es for (var arr=[], dt=new Date(start), ...). ;-)
RobG

funziona bene, ma peccato che un ciclo for (;;) non sia così leggibile per la manutenzione del software quando si lavora con molte altre persone.
Victor,

27

Uso moment.js e Twix.js che forniscono un ottimo supporto per la manipolazione di data e ora

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);

Ho questo in esecuzione su http://jsfiddle.net/Lkzg1bxb/


Ho scaricato tutti i file ad esso correlati, ma mostra ancora l'errore TypeError: moment.twix non è una funzione
vaibhav kulkarni

Potrebbe essere necessario includere le librerie. In nodejs va come, 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)

3
Per sicurezza, a differenza di quanto sopra, di solito dovresti scegliere un orario a metà giornata per evitare lievi variazioni dovute all'ora legale.
Phrogz,

Vorrei che aggiungessi anche la modifica di metà giornata al codice.
polli

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;

}

1
Ciò si bloccherebbe se si forniscono le date in ordine errato
pie6k

11

Se stai usando moment, puoi usare il loro "plugin ufficiale" per gli intervalli moment-rangee questo diventa banale.

esempio di nodo intervallo di momenti:

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')))

esempio di browser a intervalli:

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>

esempio data fns:

Se stai usando, date-fnsallora eachDayè tuo amico e ottieni di gran lunga la risposta più breve e concisa:

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>


8

Ho appena incontrato questa domanda, il modo più semplice per farlo è usare il momento:

Devi prima installare il momento e il momento:

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)

6

Sto usando la soluzione @Mohammed Safeer per un po 'e ho apportato alcuni miglioramenti. L'uso di date formulate è una cattiva pratica mentre si lavora nei controller. moment().format()dovrebbe essere usato solo a scopo di visualizzazione nelle viste. Ricorda inoltre che moment().clone()garantisce la separazione dai parametri di input, il che significa che le date di input non vengono modificate. Ti consiglio vivamente di usare moment.js quando lavori con le date.

Uso:

  • Fornire date moment.js come valori per startDate, endDateparametri
  • intervalil parametro è facoltativo e il valore predefinito è 'giorni'. Utilizzare gli intervalli supportati dal .add()metodo (moment.js). Maggiori dettagli qui
  • totalIl parametro è utile quando si specificano gli intervalli in minuti. L'impostazione predefinita è 1.

Invocare:

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

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

Funzione:

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

6

Usando ES6 hai Array.from che significa che puoi scrivere una funzione davvero elegante, che consente intervalli dinamici (ore, giorni, mesi).

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));


2
"Elegante" dipende dal tuo punto di vista. new Date(2017,12,30)è il 30 gennaio 2018, per me l'intervallo di date inizia il 29 gennaio 2018. Non tutti i giorni sono lunghi 8,64e7 ms (24 ore) in cui si osserva l'ora legale. ;-)
RobG

5

Di recente ho lavorato con moment.js, a seguito del trucco ..

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));

Il risultato sarebbe:

["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"]

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"]

1
Per favore, aggiungi più descrizione e / o informazioni sulla tua risposta e su come risolve il problema richiesto in modo che altri possano facilmente capirlo senza chiedere chiarimenti
Koceeng

Trovo che questo salta il 31-03-2016 per qualche motivo!
woodhead92,

1
Non dovresti avere varprima strDatedentro il ciclo while!
Boris Yakubchik,

2

d3js offre molte funzioni utili e include d3.time per manipolazioni della data facili

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

Per la tua specifica richiesta:

UTC

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

o ora locale

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

intervallo sarà una matrice di oggetti data che rientrano nel primo valore possibile per ogni giorno

è possibile modificare timeDay in timeHour, timeMonth ecc. per gli stessi risultati a intervalli diversi


2

Ecco una riga che non richiede librerie nel caso in cui non si desideri creare un'altra funzione. Sostituisci semplicemente startDate (in due punti) e endDate (che sono oggetti js date) con le tue variabili o i valori di data. Ovviamente potresti avvolgerlo in una funzione se preferisci

Array(Math.floor((endDate - startDate) / 86400000) + 1).fill().map((_, idx) => (new Date(startDate.getTime() + idx * 86400000)))

questo non tiene conto dell'ora legale / dell'ora legale Cambiamenti di tempo .. alcuni giorni sono più lunghi e alcuni sono più brevi
Mike

2

Uso questa funzione

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

2

Sto usando il ciclo while semplice per calcolare le date tra

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);
}


1

Nota: sono consapevole che questo è leggermente diverso dalla soluzione richiesta, ma penso che molti lo troveranno utile.

Se vuoi trovare ogni "x" intervalli (giorni, mesi, anni, ecc ...) tra due date, moment.js e i pacchetti di estensione di intervallo di momenti abilitano questa funzionalità.

Ad esempio, per trovare ogni trentesimo giorno tra due date :

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'))
});

1
  1. Genera una serie di anni:

    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. Genera un array per il mese:

            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. Genera un array per giorni:

            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())

1

Puoi farlo facilmente usando momentJS

Aggiungi momento alle tue dipendenze

npm i moment

Quindi importalo nel tuo file

var moment = require("moment");

Quindi utilizzare il seguente codice per ottenere l'elenco di tutte le date tra due date

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);

0

Questo può aiutare qualcuno,

È possibile ottenere l'output di riga da questo e formattare l'oggetto row_date come desiderato.

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


0

Ecco un metodo predefinito che accetterà le date o le stringhe del momento o una miscela come input e genererà un array di date come date del momento. Se non si desidera che le date Moment siano visualizzate come output, modificare ciò map()che restituisce il metodo.

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'));
};

0

La soluzione di @ softvar, ma includendo l'opzione delle date di lavoro

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

0

Funzione:

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

Uso:

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

Spero che ti aiuti

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.