2015-03-25 15 views
5

Nel mio codice ho bisogno di iterare tra un intervallo di date utilizzando Joda, e ho già provato questo:Iterate tra intervallo di due date utilizzando Joda

for(LocalDate currentdate = startDate; currenDate.isBefore(endDate); currenDate= currenDate.plusDays(1)){ 
    System.out.println(currentdate); 
} 

Il codice sopra funziona, ma l'iterazione si ferma quando currenDate raggiunge il giorno prima dello endDate. Quello che voglio ottenere è che l'iterazione si interrompa quando currentDate corrisponde esattamente a endDate.

for(Date currentdate = startDate; currentdate <= endDate; currentdate++){ 
    System.out.println(currentdate); 
} 

So che il codice sopra è impossibile, ma lo faccio per chiarire cosa vorrei.

risposta

7

In realtà non c'è un modo semplice intorno al codice originale voi postato, vedere la mia implementazione di seguito, appena modificato il ciclo di attuazione:

//test data 
    LocalDate startDate = LocalDate.now(); //get current date 
    LocalDate endDate = startDate.plusDays(5); //add 5 days to current date 

    System.out.println("startDate : " + startDate); 
    System.out.println("endDate : " + endDate); 

    for(LocalDate currentdate = startDate; 
      currentdate.isBefore(endDate) || currentdate.isEqual(endDate); 
      currentdate= currentdate.plusDays(1)){ 
     System.out.println(currentdate); 
    } 

sotto è l'uscita (rispetto al mio localDate):

startDate: 2015/03/26
endDate: 2015-03-31
2015-03-26
2015-03-27
2015-03-28
2015-03-29
2015 -03-30
2015-03-31

Spero che questo aiuti! Saluti. :)

+0

'!currentDate.isAfter (endDate) 'è più corto di' currentdate.isBefore (endDate) || currentdate.isEqual (endDate) '. In altre parole, usa "NON è maggiore di" in quanto una versione più breve di "è minore o uguale a". Vedi [la mia risposta] (https://stackoverflow.com/a/44320192/642706) per un esempio completo. E ora vedo [questa risposta] (https://stackoverflow.com/a/44316083/642706) ha la stessa idea, ma nel ciclo 'for' contro il mio ciclo 'while'. –

1

Non è sicuro con Joda-tipo, ma si potrebbe iterare all'intervallo (secondo, minuto, ora, giorno, mese, anno) con Calendar API, here & here sono esempi

4

Se si desidera che il ciclo di fermarsi quando la data della tua iterazione è la stessa della data di oggi, puoi usare un controllo di uguaglianza per quello.

Dai un'occhiata alla .equals() su LocalDate

Ecco un rapido esempio:

public class DateIterator { 

    public static void main(String[] args) { 

     LocalDate lastMonth = LocalDate.now().minusMonths(1); 
     LocalDate lastWeek = LocalDate.now().minusWeeks(1); 
     LocalDate yesterday = LocalDate.now().minusDays(1); 
     LocalDate today = LocalDate.now(); 
     LocalDate tomorrow = LocalDate.now().plusDays(1); 

     List<LocalDate> dates = Arrays.asList(lastMonth, lastWeek, yesterday, today, tomorrow); 

     for (LocalDate date : dates) { 
      if (date.isEqual(today)) { 
       System.out.println("Date is equal to todays date! Break out, or do something else here"); 
      } else if (date.isBefore(today)) { 
       System.out.println("The date " + date.toString() + " is in the past"); 
      } else { 
       System.out.println("The date " + date.toString() + " is in the future"); 
      } 
     } 
    } 
} 

uscita è:

The date 2015-02-25 is in the past 
The date 2015-03-18 is in the past 
The date 2015-03-24 is in the past 
Date is equal to todays date! Break out, or do something else here 
The date 2015-03-26 is in the future 

Ovviamente, se questo controllo di uguaglianza passa, sarà necessario per interrompere il ciclo ecc.

Ecco un'altra cosa utilizza una data specifica e incrementi di 1 giorno alla volta, che credo sia un po 'più simile a ciò che si vuole

public class DateIterator { 

    public static void main(String[] args) { 

     LocalDate specificDate = LocalDate.now().minusWeeks(1); 
     LocalDate today = LocalDate.now(); 

     boolean matchFound = false; 
     while (!matchFound) { 
      if (!specificDate.isEqual(today)) { 
       System.out.println(specificDate.toString() + " is in the past, incrementing day and checking again..."); 
       specificDate = specificDate.plusDays(1); 
      } else { 
       System.out.println("Date matches today!"); 
       matchFound = true; 
      } 
     } 
    } 
} 

uscita:

2015-03-18 is in the past, incrementing day and checking again... 
2015-03-19 is in the past, incrementing day and checking again... 
2015-03-20 is in the past, incrementing day and checking again... 
2015-03-21 is in the past, incrementing day and checking again... 
2015-03-22 is in the past, incrementing day and checking again... 
2015-03-23 is in the past, incrementing day and checking again... 
2015-03-24 is in the past, incrementing day and checking again... 
Date matches today! 
+0

Mi spiace di non aver capito se stavi eseguendo un iterazione su un array di date, o avessi dati fissi e aumentassi di un giorno alla volta, ma ho fornito esempi di entrambi. HTH – Jimmy

+0

grazie per la tua risposta, il tuo secondo esempio funziona, grazie: D –

2

Se si desidera che il ciclo includa l'endDate, è possibile utilizzare !currentDate.isAfter(endDate). Questo è logicamente equivalente a currentDate.isBefore(endDate) || currentDate.equals(endDate).

L'esempio seguente verrà stampato dal 6/1/2017 al 6/10/2017.

LocalDate startDate = new LocalDate(2017, 6, 1); 
LocalDate endDate = new LocalDate(2017, 6, 10); 
for (LocalDate currentDate = startDate; !currentDate.isAfter(endDate); currentDate = currentDate.plusDays(1)) 
{ 
    System.out.println(currentDate); 
} 
1

Utilizzando java.time

Il progetto Joda-Time è ora in maintenance mode, con il team di consulenza di migrazione alle java.time classi. Vedi Tutorial by Oracle.

La classe LocalDate rappresenta un valore di sola data senza ora del giorno e senza fuso orario.

LocalDate start = LocalDate.of(2017 , Month.JANUARY , 23) ; 
LocalDate stop = LocalDate.of(2017 , Month.FEBRUARY , 2) ; 

A proposito, è possibile aggiungere un controllo di integrità per verificare che il finale non sia prima dell'inizio.

Non dopo

Credo la logica che si sta cercando, per includere la data di fine, è “non dopo”. La classe LocalDate include un metodo isAfter, al quale è possibile aggiungere un "NOT" logico (!).

Inoltre, un loop while sembra più appropriato e autoesplicativo in questa situazione rispetto al ciclo for.

LocalDate ld = start ; 
List<LocalDate> dates = new ArrayList<>() ; 
while (! ld.isAfter(stop)) { 
    dates.add(ld); // Collect this date. 
    ld = ld.plusDays(1) ; // Setup the next loop. 
} 

Vedere questo code run live at IdeOne.com.

date: [2017-01-23, 2017-01-24, 2017-01-25, 2017-01-26, 2017-01-27, 2017-01-28, 2017-01-29 , 2017/01/30, 2017/01/31, 2017/02/01, 2017/02/02]

semiaperta

l'iterazione si ferma quando currentDate raggiunge il giorno prima endDate

Questo è effettivamente auspicabile. Conosciuto come Half-Open, l'approccio comune nella gestione della data-ora è considerare l'inizio come compreso mentre il finale è esclusivo. Quindi una pausa pranzo inizia alle 12:00:00 (mezzogiorno) e arriva fino a, ma non include, 13:00:00 (13:00). Il mese di gennaio inizia il 1 ° gennaio e arriva fino a, ma non include, il 1 ° febbraio. Una settimana inizia il lunedì e arriva fino a, ma non include il lunedì successivo. Molto utile, questo approccio evita il problema di determinare l'ultimo secondo di una data-ora in cui alcuni sistemi usano millisecondi (x.999), alcuni (x.999999), stessi nanosecondi (x.999999999), e altri usano variazioni come come 5 posizioni decimali (x.99999). Invece andiamo a, ma non includo, il primo momento della prossima ora o giorno ecc.

Trovo che l'utilizzo dell'approccio Half-Open in modo coerente nel mio codice semplifica la lettura del codice, la comprensione più facile e molto meno probabile che si traduca in bug fuori-da-uno. Sono stato coinvolto in innumerevoli problemi di mistero finanziario che si sono rivelati confusione o malintesi su un rapporto che riguardava la data per le date inclusive vs exclusive. Quindi, se possibile, istruisci i tuoi utenti a pensare in modo coerente alla modalità semi-aperta. Se non è fattibile, regola il tuo codice in modo che la tua logica e i loop utilizzino Half-Open internamente almeno.

Ecco un codice simile a quello precedente, ma utilizzando isBefore anziché NOT isAfter, per utilizzare l'approccio Half-Open. Il finale è il 3 febbraio invece del 2 febbraio.

LocalDate start = LocalDate.of(2017 , Month.JANUARY , 23) ; 
LocalDate stop = LocalDate.of(2017 , Month.FEBRUARY , 3) ; // Third instead of the Second of February, to be half-open. 

LocalDate ld = start ; 
List<LocalDate> dates = new ArrayList<>() ; 
while (ld.isBefore(stop)) { // Using "isBefore" for Half-Open approach. 
    dates.add(ld); // Collect this date. 
    ld = ld.plusDays(1) ; // Setup the next loop. 
} 

Vedere questo code run live at IdeOne.com.

inizio: 2017-01-23 | stop: 2017-02-03

date: [2017-01-23, 2017-01-24, 2017-01-25, 2017-01-26, 2017-01-27, 2017-01-28, 2017/01/29, 2017/01/30, 2017/01/31, 2017/02/01, 2017/02/02]


Chi java.time

Il quadro java.time è integrato in Java 8 e versioni successive. Queste classi soppiantano le fastidiose classi data legacy come java.util.Date, Calendar, & SimpleDateFormat.

Il progetto Joda-Time, ora in maintenance mode, consiglia la migrazione alle classi java.time.

Per ulteriori informazioni, vedere Oracle Tutorial. E cerca Stack Overflow per molti esempi e spiegazioni. La specifica è JSR 310.

Dove ottenere le classi java.time?

Il progetto ThreeTen-Extra java.time prolunga con classi aggiuntive. Questo progetto è un terreno di prova per possibili aggiunte future a java.time. È possibile trovare alcune classi utili come Interval, YearWeek, YearQuarter e more.

Problemi correlati