2012-12-05 7 views
5

Ich bin auf der Suche nach einer schönen Möglichkeit zu validieren und dann eine Datumszeichenfolge aus einem REST-Service zu vergleichen.Vergleichen von Datumszeichenfolgen mit tatsächlichen Daten in Scala

Wenn ich 2012-12-25 (Jahr-Monat-Tag) als Zeichenfolge übergeben, was wäre eine elegante Möglichkeit zu bestätigen, es ist ein gültiges Datum, und dann zu sagen, dass das Datum in der Zukunft oder in ist die Vergangenheit?

Um mit Daten in Scala zu arbeiten, kann man natürlich vorhandene Java-Bibliotheken verwenden. Aber das Arbeiten mit Daten in Java war immer wie das Dienen der dunklen Seite, also möchte ich nicht zu viel dieses Vermächtnis in meinen gegenwärtigen Kodierungsstil ziehen. Wenn man sich die Scala Dates example on langref.org anschaut, fühlt es sich an, dass ich zurück zum Programmieren von Java komme, wenn ich diese Art der Programmierung befolge.

+2

Ich bin kein Scala-Experte, aber vielleicht könnte der [Joda Time Wrapper mit dem Namen 'Scala Time'] (https://github.com/jorgeortiz85/scala-time) für Sie arbeiten. .. –

Antwort

5

JodaTime ist in Ordnung, gut, gut, mach dir keine Sorgen über die dunkle Seite, es existiert nicht (oder zumindest nicht in dieser speziellen Java-Bibliothek).

// "20121205".to_date 
class String2Date(ymd: String) { 
    def to_date = { 
    try{ Some(ymdFormat.parseDateTime(ymd)) } 
    catch { case e:Exception => None } 
    } 
    val ymdFormat = org.joda.time.format.DateTimeFormat.forPattern("yyyyMMdd") 
} 
@inline implicit final def string2Date(ymd: String) = new String2Date(ymd) 

def dater(ymd: String) = { 
    val other = new JodaTime 
    ymd.to_date map{d=> 
    if(d.isBefore other) ... 
    else ... 
    } getOrElse("bad date format") 
} 

Kann praktisch alles Datum/Zeit im Zusammenhang mit JodaTime tun; es ist absurd, wie gut diese Bibliothek ist: eindeutiger Daumen hoch.

+0

Sieht aus wie eine gute Option, danke. Würden Sie normalerweise das Projekt scala-time (https://github.com/jorgeortiz85/scala-time) verwenden? – Jack

+0

nein, habe keinen Bedarf für ScalaTime gefunden, JodaTime wie es ist, ist ziemlich kurz; d. h. die DSL-Erweiterungen, die ScalaTime aktiviert, sind für meine Bedürfnisse nicht essentiell.JodaTime arbeitet nahtlos mit Scala, Java Interop Proof in Aktion ;-) – virtualeyes

+0

+1 Für JodaTime über Java Date-Bibliotheken * yuck * – fresskoma

3

Sie können dies die Standard-Java Simple Bibliothek tun mit:

def parseDate(value: String) = { 
    try { 
    Some(new SimpleDateFormat("yyyy-MM-dd").parse(value)) 
    } catch { 
    case e: Exception => None 
    } 
} 

Und es dann wie so verwendet:

parseDate("2012-125") // None 
parseDate("2012-12-05") // Some(Wed Dec 05 00:00:00 EST 2012) 

Dann können Sie zum Testen zukünftige Termine eine Funktion haben:

def isFuture(value: Date) = value.after(new Date) 
+0

+1 Schön erklärt, danke – Jack

1

Zwar gibt es einige Nachteile für die Verwendung der Java-Date-Bibliotheken wie ein Fehlen von t hread Sicherheit (Why is Java's SimpleDateFormat not thread-safe?) und eine harte API zu verwenden, könnten Sie implicits verwenden, um die Dinge ein wenig schmackhafter zu machen:

implicit def stringToDate(date: String) = new { 
    def parse(implicit format: String) = parse0(date)(format) 
    private def parse0(date: String)(implicit format: String) = { 
    val sdf = new SimpleDateFormat(format) 
    sdf.setLenient(false) 
    sdf.parse(date) 
    } 
    def isValid(implicit format: String) = try { parse0(date)(format); true } catch { case _ => false } 
    def beforeNow(implicit format: String) = parse0(date)(format) before new Date() 
    def afterNow(implicit format: String) = parse0(date)(format) after new Date() 
} 

Dann es so könnten Sie verwenden:

implicit val format = "yyyy-MM-dd" 
"2012-12-02" isValid // true 
"2012-12-02" beforeNow // ? 
"2012-12-25" afterNow // ? 

Oder könnten Sie verwenden scala-time:

import org.joda.time.format.ISODateTimeFormat._ 
import org.joda.time.DateTime 
for(date <- date.parseOption("2012-12-02")) yield date < new DateTime // Option(?) 

Mit diesem Ansatz erhalten Sie eine Scala freundliche Oberfläche, und Sie müssen nicht erstellen und ein neues Objekt Simple analysieren oder sie speichern in auf hread local, um Threading-Probleme zu vermeiden.

1

Wenn Sie wirklich keine Datumszeitbibliothek verwenden möchten, können Sie einen geeigneten regulären Ausdruck (wie den in dieser Antwort: https://stackoverflow.com/a/7221570/227019) verwenden, um zu überprüfen, ob die Zeichenfolge tatsächlich ein gültiges ISO 8601-Datum ist. Verwenden Sie dann die Tatsache, dass solche Daten lexikographisch verglichen werden können, um ihre zeitliche Reihenfolge zu bestimmen (formatieren Sie einfach das aktuelle Datum im selben Format und vergleichen Sie es mit dem anderen Datum, indem Sie einen regulären Stringvergleich verwenden).

Verwandte Themen