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!

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.


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


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
}

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>


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

}


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
}

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

0

Si quieres una manera eficiente con milisegundos:

var daysOfYear = [];
for (var d = begin; d <= end; d = d + 86400000) {
    daysOfYear.push(new Date(d));
}

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

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

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.