2012-12-05 77 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格式化日期,然后使用这样的事实,即这些日期可以按字母顺序进行比较以确定它们的时间顺序(简单地使用相同的格式格式化当前日期,并使用常规字符串比较与其他日期进行比较)。