Pętla JavaScript między zakresami dat

135

Biorąc pod uwagę dwa Date()obiekty, z których jeden jest mniejszy od drugiego, jak codziennie wykonywać pętlę między datami?

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

}

Czy taka pętla zadziała? Ale jak mogę dodać jeden dzień do licznika pętli?

Dzięki!

Tom Gullen
źródło

Odpowiedzi:

201

Oto sposób, aby to zrobić, wykorzystując sposób, w jaki dodanie jednego dnia powoduje przeniesienie daty na następny miesiąc, jeśli to konieczne, i bez mieszania się z milisekundami. Oszczędność światła dziennego też nie jest problemem.

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

Pamiętaj, że jeśli chcesz zachować datę, musisz utworzyć nową (jak powyżej new Date(d)), w przeciwnym razie każda zapisana data będzie ostateczną wartością dw pętli.

David Johnstone
źródło
O wiele bardziej czytelne niż wszystkie inne odpowiedzi. Dodanie 86400000 milisekund do każdej pętli jest mało czytelne.
Owen
1
Uważaj na czas letni. d.getDate () + 1, gdy d.getDate () = GMT N i d.getDate () + 1 = GMT N - 1 d.getDate () + 1 zwraca ten sam dzień miesiąca dwukrotnie.
Rafael Fontes
1
Dlaczego Date.now()podczas definiowania now? new Date() domyślnie zwraca bieżącą datę jako obiekt . Wywołanie Datebez newkonstruktora daje po prostu ciąg Date, który i tak konwertujesz na obiekt Date?
tatlar
Dla mnie new Date(2012, 0, 1);odebranie niewłaściwego dnia (dzień wcześniej), new Date(Date.UTC(2012, 0, 1))działało dobrze.
Tk421
Wypróbowałem wiele rozwiązań w Internecie. Dziwne jest to, że czasami przeskakuje. Podobnie jak 1.12, 2.12, 3.12, 5.12 ... (zauważ, że 4.12 jest pomijane) nie mam pojęcia, dlaczego tak się dzieje ... Czy ktoś ma ten problem i znalazł rozwiązanie?
Erik Kubica
73

Na podstawie odpowiedzi Toma Gullena.

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
źródło
Co musisz zaimportować, aby tego używać?
DevAllanPer
3
@DevAllanPer nic, Datejest globalnym deweloperem
Dmitri Pisarev
9

Jeśli startDate i endDate są rzeczywiście obiektami daty, możesz przekonwertować je na liczbę milisekund od północy 1 stycznia 1970 roku, na przykład:

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

Następnie możesz zapętlać od jednej do drugiej, zwiększając loopTime o 86400000 (1000 * 60 * 60 * 24) - liczbę milisekund w ciągu jednego dnia:

for(loopTime = startTime; loopTime < endTime; loopTime += 86400000)
{
    var loopDay=new Date(loopTime)
    //use loopDay as you wish
}
jayarjo
źródło
1
+1, dało mi wystarczająco dużo pracy, w moim pytaniu
znalazłem
5
nie działa to w przypadku zapętlenia zmiany czasu letniego (w obszarach, w których jest to problem). Poza tym dobre rozwiązanie.
czadgh
3
Nie możesz zakładać, że dzień ma 86400000kilka sekund. Ta pętla jest wrażliwa na zmiany czasu letniego i inne warunki brzegowe.
Jeremy J Starcher
2
Oprócz czasu letniego, kolejnym warunkiem krawędzi jest „sekunda przestępna”. Jednosekundowym różnica nie ma znaczenia - Termin przekształcić w milisekundach odpowiadają pierwszej sekundzie danego dnia. Jeden drugi błąd i wylądujesz poprzedniego dnia.
Wojtek Kruszewski
9

Myślę, że znalazłem jeszcze prostszą odpowiedź, jeśli pozwolisz sobie na użycie 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
źródło
5

Tutaj prosty działający kod zadziałał dla mnie

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
źródło
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
źródło
1

Opierając się na odpowiedzi Tabare, musiałem na koniec dodać jeszcze jeden dzień, ponieważ cykl został wcześniej skrócony

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
źródło
0

Jeśli chcesz wydajnie pracować w milisekundach:

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

Załóżmy, że masz datę początkową i końcową z interfejsu użytkownika i zapisałeś je w zmiennej zakresu w kontrolerze.

Następnie zadeklaruj tablicę, która będzie resetowana przy każdym wywołaniu funkcji, aby przy następnym wywołaniu funkcji mogły zostać zapisane nowe dane.

var dayLabel = [];

Pamiętaj, aby użyć nowej daty (zmiennej początkowej), ponieważ jeśli nie użyjesz nowej daty i bezpośrednio przypiszesz ją do zmiennej, funkcja setDate zmieni pierwotną wartość zmiennej w każdej iteracji.

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

Na podstawie odpowiedzi Jayarjo:

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

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

    alert(loopDay);

    loopDate.setTime(loopDate.valueOf() + 86400000);
}
Tom Gullen
źródło
Jeden komentarz do tego jest taki, że preferowane jest porównanie mniejsze niż! =, Jak w przypadku pętli przez wiele miesięcy z jakiegoś powodu! = Porównanie nigdy się nie uruchamia.
Tom Gullen
1
Oprócz czasu letniego, kolejnym warunkiem krawędzi jest „sekunda przestępna”. Jednosekundowym różnica nie ma znaczenia - Termin przekształcić w milisekundach odpowiadają pierwszej sekundzie danego dnia. Jeden drugi błąd i wylądujesz poprzedniego dnia.
Wojtek Kruszewski