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!

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.


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

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
}

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>


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

}


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

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

0

Jeśli chcesz wydajnie pracować w milisekundach:

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

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

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

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.