【问题标题】:Comparing date strings with actual dates in Scala将日期字符串与 Scala 中的实际日期进行比较
【发布时间】:2012-11-23 17:45:17
【问题描述】:

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

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

要在 Scala 中处理日期,显然可以使用现有的 Java 库。但是,在 Java 中处理日期一直就像为黑暗面服务,所以我不想将太多的遗留问题拖入我当前的编码风格中。看着Scala Dates example on langref.org,感觉如果我按照这种编程风格,我会回到编码Java的。

【问题讨论】:

标签: scala


【解决方案1】:

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 相关的日期/时间;这个库有多好真是荒谬:毫不含糊地竖起大拇指。

【讨论】:

  • 看起来是个不错的选择,谢谢。你通常会使用 scala-time (github.com/jorgeortiz85/scala-time) 项目吗?
  • 不,还没有发现需要ScalaTime,JodaTime原样相当简洁;即 ScalaTime 所采用的 DSL 增强对我的需求来说并不是必不可少的。 JodaTime 与 Scala 无缝协作,Java 互操作证明在行动 ;-)
【解决方案2】:

您可以使用标准的 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)

【讨论】:

    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      虽然使用 java 日期库有一些缺点,例如缺乏线程安全性 (Why is Java's SimpleDateFormat not thread-safe?) 和难以使用的 API,但您可以使用隐式来使事情变得更容易接受:

      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 对象或将其存储在本地线程中以避免线程问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多