Bucle de JavaScript entre rangos de fechas

135

Dados dos Date()objetos, donde uno es menor que el otro, ¿cómo hago un bucle todos los días entre las fechas?

for(loopDate = startDate; loopDate < endDate; loopDate += 1)
{

}

¿Funcionaría este tipo de bucle? Pero, ¿cómo puedo agregar un día al contador de bucles?

¡Gracias!

Tom Gullen
fuente

Respuestas:

201

Aquí hay una manera de hacerlo haciendo uso de la forma en que agregar un día hace que la fecha se transfiera al siguiente mes si es necesario, y sin perder el tiempo con milisegundos. El horario de verano tampoco es un problema.

var now = new Date();
var daysOfYear = [];
for (var d = new Date(2012, 0, 1); d <= now; d.setDate(d.getDate() + 1)) {
    daysOfYear.push(new Date(d));
}

Tenga en cuenta que si desea almacenar la fecha, necesitará hacer una nueva (como se indica arriba con new Date(d)), o de lo contrario terminará con cada fecha almacenada como el valor final de den el ciclo.

David Johnstone
fuente
Mucho más legible que todas las otras respuestas. Agregar 86400000 milisegundos a cada ciclo no es muy legible.
Owen
1
Tenga cuidado con los horarios de verano. d.getDate () + 1 cuando d.getDate () = GMT N y d.getDate () + 1 = GMT N - 1 d.getDate () + 1 devuelve el mismo día del mes dos veces.
Rafael Fontes
1
¿Por qué hacer Date.now()al definir now? new Date() devuelve la fecha actual como un objeto por defecto . ¿Llamar Datesin el newconstructor solo le da una cadena de fecha que luego convierte en un objeto de fecha?
tatlar
Para mí new Date(2012, 0, 1);fue recoger el día incorrecto (un día antes), new Date(Date.UTC(2012, 0, 1))funcionó bien.
Tk421
He intentado múltiples soluciones en internet. Extraño es que a veces se salta algunos días. Como 1.12, 2.12, 3.12, 5.12 ... (observe que se omite 4.12) no tengo idea de por qué sucede ... ¿Alguien tiene este problema y encuentra una solución?
Erik Kubica
73

Basado en la respuesta de Tom Gullen.

var start = new Date("02/05/2013");
var end = new Date("02/10/2013");


var loop = new Date(start);
while(loop <= end){
   alert(loop);           

   var newDate = loop.setDate(loop.getDate() + 1);
   loop = new Date(newDate);
}
Tabares
fuente
¿Qué tienes que importar para usar esto?
DevAllanPer
3
@DevAllanPer nothing, Datees un objeto global developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Dmitri Pisarev el
9

Si startDate y endDate son de hecho objetos de fecha, podría convertirlos a un número de milisegundos desde la medianoche del 1 de enero de 1970, de esta manera:

var startTime = startDate.getTime(), endTime = endDate.getTime();

Luego, podría pasar de uno a otro incrementando loopTime en 86400000 (1000 * 60 * 60 * 24) - número de milisegundos en un día:

for(loopTime = startTime; loopTime < endTime; loopTime += 86400000)
{
    var loopDay=new Date(loopTime)
    //use loopDay as you wish
}
jayarjo
fuente
1
+1, me dio suficiente para trabajar, he incluido la solución de trabajo en mi pregunta
Tom Gullen
55
esto no funciona al pasar un cambio de horario de verano (en áreas donde eso es un problema). Buena solución de lo contrario.
chadgh
3
No puedes asumir que hay 86400000segundos en un día. Este bucle es frágil a los cambios de horario de verano y otras condiciones de borde.
Jeremy J Starcher
2
Además del horario de verano, otra condición de borde es "Leap Second". Una diferencia de un segundo es importante: las fechas convertidas a milisegundos corresponden al primer segundo de un día determinado. Un segundo error y aterrizas el día anterior.
Wojtek Kruszewski
9

Creo que encontré una respuesta aún más simple, si te permites usar Moment.js :

// cycle through last five days, today included
// you could also cycle through any dates you want, mostly for
// making this snippet not time aware
const currentMoment = moment().subtract(4, 'days');
const endMoment = moment().add(1, 'days');
while (currentMoment.isBefore(endMoment, 'day')) {
  console.log(`Loop at ${currentMoment.format('YYYY-MM-DD')}`);
  currentMoment.add(1, 'days');
}
<script src="https://cdn.jsdelivr.net/npm/moment@2/moment.min.js"></script>

vvo
fuente
5

Aquí un código de trabajo simple, funcionó para mí

var from = new Date(2012,0,1);
var to = new Date(2012,1,20);
    
// loop for every day
for (var day = from; day <= to; day.setDate(day.getDate() + 1)) {
      
   // your day is here

}

Amr Ibrahim
fuente
2
var start = new Date("2014-05-01"); //yyyy-mm-dd
var end = new Date("2014-05-05"); //yyyy-mm-dd

while(start <= end){

    var mm = ((start.getMonth()+1)>=10)?(start.getMonth()+1):'0'+(start.getMonth()+1);
    var dd = ((start.getDate())>=10)? (start.getDate()) : '0' + (start.getDate());
    var yyyy = start.getFullYear();
    var date = dd+"/"+mm+"/"+yyyy; //yyyy-mm-dd

    alert(date); 

    start = new Date(start.setDate(start.getDate() + 1)); //date increase by 1
}
MaxEcho
fuente
1

Según la respuesta de Tabare, tuve que agregar un día más al final, ya que el ciclo se corta antes

var start = new Date("02/05/2013");
var end = new Date("02/10/2013");
var newend = end.setDate(end.getDate()+1);
var end = new Date(newend);
while(start < end){
   alert(start);           

   var newDate = start.setDate(start.getDate() + 1);
   start = new Date(newDate);
}
Carlos Vizcaya Savchenco
fuente
0

Si quieres una manera eficiente con milisegundos:

var daysOfYear = [];
for (var d = begin; d <= end; d = d + 86400000) {
    daysOfYear.push(new Date(d));
}
Guilherme Simão Couto
fuente
0

Supongamos que obtuvo la fecha de inicio y la fecha de finalización de la interfaz de usuario y la almacenó en la variable de alcance en el controlador.

Luego declare una matriz que se restablecerá en cada llamada de función para que en la próxima llamada para la función se puedan almacenar los nuevos datos.

var dayLabel = [];

Recuerde usar la nueva Fecha (su variable inicial) porque si no usa la nueva fecha y la asigna directamente a la variable, la función setDate cambiará el valor de la variable original en cada iteración`

for (var d = new Date($scope.startDate); d <= $scope.endDate; d.setDate(d.getDate() + 1)) {
                dayLabel.push(new Date(d));
            }
Utkarsh Joshi
fuente
-2

Basado en la respuesta de Jayarjo:

var loopDate = new Date();
loopDate.setTime(datFrom.valueOf());

while (loopDate.valueOf() < datTo.valueOf() + 86400000) {

    alert(loopDay);

    loopDate.setTime(loopDate.valueOf() + 86400000);
}
Tom Gullen
fuente
Un comentario para esto es que se prefiere una comparación menor que!!, Como cuando se repite durante varios meses por alguna razón, la comparación! = Nunca se activa.
Tom Gullen
1
Además del horario de verano, otra condición de borde es "Leap Second". Una diferencia de un segundo es importante: las fechas convertidas a milisegundos corresponden al primer segundo de un día determinado. Un segundo error y aterrizas el día anterior.
Wojtek Kruszewski