2012-12-05 277 views
5

我正在尋找一種很好的方法來驗證並比較從REST服務傳遞的日期字符串。在Scala中比較日期字符串和實際日期

如果我將2012-12-25(year-month-day)作爲字符串傳遞,那麼確定這是一個有效日期,然後說日期處於將來或在過去?

要在Scala中處理日期,顯然可以使用現有的Java庫。但是,在Java中使用日期一直就像服務黑暗的一面,所以我不想將過多的遺留問題拖入我當前的編碼風格。看看Scala Dates example on langref.org,如果遵循這種編程風格,感覺我會回到編碼Java。

+2

我不是一個斯卡拉專家,但也許[斯達拉時間的Joda時間包裝]](https://github.com/jorgeortiz85/scala-time)可以爲你工作。 .. –

回答

5

JodaTime很好,很好,很好,不要擔心黑暗的一面,它不存在(或者至少不在這個特定的Java庫中)。

// "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") 
} 

幾乎可以做任何與JodaTime相關的日期/時間;這個圖書館有多好是荒謬的:毫不含糊的豎起大拇指。

+0

看起來像一個很好的選擇,謝謝。你通常會使用scala-time(https://github.com/jorgeortiz85/scala-time)項目嗎? – Jack

+0

不,沒有發現需要ScalaTime,JodaTime是相當簡潔的;即ScalaTime所使用的DSL增強功能對我的需求並不重要。JodaTime可與Scala,Java interop證明無縫協作;-) – virtualeyes

+0

+1針對Java日期庫的JodaTime * yuck * – fresskoma

3

爲此,可以使用標準的Java的SimpleDateFormat庫做:

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

然後用它像這樣:

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

然後你就可以擁有用於測試未來日期的功能:

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

+1很好解釋,謝謝 – Jack

1

儘管使用java日期庫存在一些缺點,例如缺少t hread安全(Why is Java's SimpleDateFormat not thread-safe?)和難用的API,你可以使用implicits使事情多一點可口:

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

然後,你可以使用這樣的:

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

或者,你可以使用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(?) 

通過這種方法,你會得到一個斯卡拉友好的界面,和你沒有創建和解析一個新的SimpleDateFormat對象或將其存儲在希望避免線程問題。

1

如果你真的想避免使用任何日期時間庫,你可以使用合適的正則表達式(例如這個答案中的那個:https://stackoverflow.com/a/7221570/227019)來驗證該字符串確實是一個有效的ISO 8601格式化日期,然後使用這樣的事實,即這些日期可以按字母順序進行比較以確定它們的時間順序(簡單地使用相同的格式格式化當前日期,並使用常規字符串比較與其他日期進行比較)。