将日期字符串与Scala中的实际日期进行比较

时间:2012-12-05 19:35:55

标签: scala

我正在寻找一种很好的方法来验证,然后比较从REST服务传递的日期字符串。

如果我将2012-12-25(年 - 月 - 日)作为字符串传递,那将是一种优雅的方式来确认它是一个有效的日期,然后说明日期是在将来还是在过去?

要在Scala中使用日期,显然可以使用现有的Java库。但是,使用Java中的日期一直就像服务于黑暗面,所以我不想将太多的遗产拖到我当前的编码风格中。看看Scala Dates example on langref.org,如果我遵循这种编程方式,我会觉得我将重新编写Java。

4 个答案:

答案 0 :(得分: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相关的日期/时间;这个图书馆有多好,这是荒谬的:明确的赞许。

答案 1 :(得分: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)

答案 2 :(得分:1)

尽管使用java日期库存在一些缺点,例如缺乏线程安全性(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(?)

使用这种方法,您将获得一个Scala友好的接口,您不必创建和解析新的SimpleDateFormat对象,也不必将其存储在本地线程中以避免线程问题。

答案 3 :(得分:1)

如果你真的想完全避免使用任何日期时间库,你可以使用合适的正则表达式(例如本答案中的那个:https://stackoverflow.com/a/7221570/227019)来验证字符串确实是有效的ISO 8601格式化日期,然后使用这样的事实,即可以按字典顺序对这些日期进行比较,以确定它们的时间顺序(只需使用相同格式格式化当前日期,并使用常规字符串比较将其与其他日期进行比较)。