2015-05-11 21 views
5

Data una data di inizio e una data di fine, vorrei eseguirne l'iterazione di giorno utilizzando una foreach, una mappa o una funzione simile. Qualcosa di simileIterate over date range (the scala way)

(DateTime.now to DateTime.now + 5.day by 1.day).foreach(println) 

Sto usando https://github.com/nscala-time/nscala-time, ma ho restituito un oggetto joda Interval se uso la sintassi di cui sopra, che ho il sospetto non è anche un intervallo di date, ma una sorta di serie di millisecondi.

MODIFICA: la domanda è obsoleta. Come consigliato sulla home page di joda, se si utilizza java 8 è necessario iniziare o migrare a java.time.

+0

appena aggiunto 'nscala-time' Dipendenza e scritto '(DateTime.now to DateTime.now + (5 giorni) per (1 giorno)). foreach (println) '. Funziona come la magia – Odomontois

+0

Ottengo: valore di non è un membro di org.joda.time.Interval –

+1

Questo è praticamente il mio codice https://gist.github.com/Odomontois/ea73f9bbfcb4cdc5f1b6 – Odomontois

risposta

17

È possibile utilizzare plusDays:

val now = DateTime.now 
(0 until 5).map(now.plusDays(_)).foreach(println) 

Attribuite di inizio e fine date:

import org.joda.time.Days 

val start = DateTime.now.minusDays(5) 
val end = DateTime.now.plusDays(5)  

val daysCount = Days.daysBetween(start, end).getDays() 
(0 until daysCount).map(start.plusDays(_)).foreach(println) 
+0

grazie, ma il punto è che ho data di inizio e fine –

+0

@GismoRanas ha aggiornato la risposta di conseguenza. –

1

si può usare qualcosa di simile:

object Test extends App { 
    private val startDate: DateTime = DateTime.now() 
    private val endDate: DateTime = DateTime.now().plusDays(5) 
    private val interval: Interval = new Interval(startDate, endDate) 
    Stream.from(0,1) 
     .takeWhile(index => interval.contains(startDate.plusDays(index))) 
     .foreach(index => println(startDate.plusDays(index))) 
} 
10

Per solo l'iterazione di giorno, ho do:

Iterator.iterate(start) { _ + 1.day }.takeWhile(_.isBefore(end)) 

Questo ha dimostrato di essere abbastanza che ho un oggetto piccolo aiutante di fornire un implicito e consentire un tipo di trasformazione utile: l'utilizzo

object IntervalIterators { 
    implicit class ImplicitIterator(val interval: Interval) extends AnyVal { 
    def iterateBy(step: Period): Iterator[DateTime] = Iterator.iterate(interval.start) { _ + step } 
     .takeWhile(_.isBefore(interval.end)) 

    def iterateBy[A](step: Period, transform: DateTime => A): Iterator[A] = iterateBy(step).map(transform) 

    def iterateByDay: Iterator[LocalDate] = iterateBy(1.day, { _.toLocalDate }) 

    def iterateByHour: Iterator[DateTime] = iterateBy(1.hour) 
    } 
} 

Esempio:

import IntervalIterators._ 

(DateTime.now to 5.day.from(DateTime.now)).iterateByDay // Iterator[LocalDate] 

(30.minutes.ago to 1.hour.from(DateTime.now)).iterateBy(1.second) // Iterator[DateTime], broken down by second 
2

Solution con java.time API utilizzando Scala

necessaria l'importazione e l'inizializzazione

import java.time.temporal.ChronoUnit 
import java.time.{LocalDate, Period} 

val now = LocalDate.now 

Crea lista dei LocalDate per la durata del campione

(0 to 5) 
    .map(days => now.plusDays(days)) 
    .foreach(println) 

iterare su date specifiche tra inizio e di fine

//Extract the duration 
val duration = Period 
    .between(now, now.plusDays(5)) 
    .get(ChronoUnit.DAYS) 
//val duration = now.compareTo(now.plusDays(5)) 

//Create list for the duration 
(0 to duration) 
    .map(days => now.plusDays(days)) 
    .foreach(println) 
0
import java.util.{Calendar, Date} 
import scala.annotation.tailrec 

/** Gets date list between two dates 
    * 
    * @param startDate Start date 
    * @param endDate End date 
    * @return   List of dates from startDate to endDate 
    */ 
def getDateRange(startDate: Date, endDate: Date): List[Date] = { 
    @tailrec 
    def addDate(acc: List[Date], startDate: Date, endDate: Date): List[Date] = { 
    if (startDate.after(endDate)) acc 
    else addDate(endDate :: acc, startDate, addDays(endDate, -1)) 
    } 

    addDate(List(), startDate, endDate) 
} 

/** Adds a date offset to the given date 
    * 
    * @param date  ==> Date 
    * @param amount  ==> Offset (can be negative) 
    * @return   ==> New date 
    */ 
def addDays(date: Date, amount: Int): Date = { 
    val cal = Calendar.getInstance() 
    cal.setTime(date) 
    cal.add(Calendar.DATE, amount) 
    cal.getTime 
} 
+0

Per favore, no, non 'java.util.Date' di nuovo ... Siamo già in scala. Ma 'java.util.Date' è morto anche a Java anni fa, e c'è già una risposta accettata con' DateTime'. –

Problemi correlati