Scala / Lift检查日期是否格式正确

时间:2011-05-12 18:16:49

标签: scala lift

我的电梯应用程序中有一个日期输入框,我想检查用户输入的日期格式是否正确: dd / mm / yyyy

如何在scala中为此编写正则表达式检查?我看过模式匹配示例 - 但这看起来过于复杂。

PS:我不必使用正则表达式,欢迎任何其他选择!

5 个答案:

答案 0 :(得分:11)

SimpleDateFormat是非常丑陋的(更令人不安的是)非线程安全。如果你试图在2个或更多线程中同时使用相同的实例,那么期望事情以最令人不愉快的方式爆炸。

JodaTime更好:

import org.joda.time.format._
val fmt = DateTimeFormat forPattern "dd/MM/yyyy"
val input = "12/05/2009"
val output = fmt parseDateTime input

如果它抛出IllegalArgumentException,则日期无效。

由于我怀疑您想知道实际日期是否有效,您可能希望返回Option[DateTime]None如果无效。

def parseDate(input: String) = try {
  Some(fmt parseDateTime input)
} catch {
  case e: IllegalArgumentException => None
}

或者,如果无法格式化,请使用Either捕获实际异常:

def parseDate(input: String) = try {
  Right(fmt parseDateTime input)
} catch {
  case e: IllegalArgumentException => Left(e)
}

<强>更新

要使用Either,您有两个主要策略:

映射双方之一:

parseDate(input).left map (_.getMessage)
//will convert the Either[IllegalArgumentException, DateTime]
//to an Either[String, DateTime]
折叠它:

parseDate(input) fold (
  _ => S.error(
    "birthdate",
    "Invalid date. Please enter date in the form dd/mm/yyyy."),
  dt => successFunc(dt)
)

当然,这两个可以组成:

parseDate(input).left map (_.getMessage) fold (
  errMsg => S.error("birthdate", errMsg), //if failure (Left by convention)
  dt => successFunc(dt) //if success (Right by convention)
)

答案 1 :(得分:1)

我不会使用正则表达式,而是使用SimpleDateFormat(这不是那么简单,我们将会看到)。

一个正则表达式处理允许28和30作为日,但不是38,不同的月长和闰年,可能是一个有趣的挑战,但不适用于现实世界的代码。

val df = new java.text.SimpleDateFormat ("dd/MM/yyyy")

(我假设M在大月,而不是像小分钟那样)。

现在,让我们从一个错误开始:

scala> df.parse ("09/13/2001")                                
res255: java.util.Date = Wed Jan 09 00:00:00 CET 2002
跳跃 - 它是非常宽容的,并且包裹了几个月到第二年。但我们可以通过第二个格式化过程来实现它:

scala> val sInput = "13/09/2001"
sInput: java.lang.String = 13/09/2001

scala> sInput.equals (df.format (df.parse (sInput))) 
res259: Boolean = true

scala> val sInput = "09/13/2001"                     
sInput: java.lang.String = 09/13/2001

scala> sInput.equals (df.format (df.parse (sInput))) 
res260: Boolean = false

我希望你不一定要使用正则表达式,并且可以使用它。

答案 2 :(得分:1)

如用户未知的那样,您应该使用一些知道如何正确处理日期的库,包括每个特定月份和闰年的天数。

对于字段翻转,

SimpleDateFormat不是非常直观,并且最初仅通过滚动其他字段来接受错误的日期。为防止它这样做,您必须在其上调用setLenient(false)。另请注意,SimpleDateFormat不是线程安全的,因此每次要使用它时都需要创建一个新实例:

def validate(date: String) = try {
    val df = new SimpleDateFormat("dd/MM/yyyy")
    df.setLenient(false)
    df.parse(date)
    true
  } catch {
    case e: ParseException => false
  }

或者您也可以使用Joda Time,它比Java Date API更直观,并提供线程安全的日期格式:

val format = DateTimeFormat.forPattern("dd/MM/yyyy")

def validate(date: String) = try {
    format.parseMillis(date)
    true
  }
  catch {
    case e: IllegalArgumentException => false
  }

答案 3 :(得分:1)

从中我们可以在字符串中验证日期,并通过解析“dd / MM / yyyy”等格式获得预期的日期响应。

  try {  val format = DateTimeFormat.forPattern("dd/MM/yyyy")
  format.parseMillis(dateInString)
  val df = new SimpleDateFormat("dd/MM/yyyy")
  val newDate = df.parse(dateInString)
  true
    } catch {
      case e: ParseException => false

      case e: IllegalArgumentException => false
    }

答案 4 :(得分:1)

在对象中定义DateTimeFormatter实例是一种很好的做法,因为它是线程安全且不可变的。

  object DateOfBirth{
    import org.joda.time.format.DateTimeFormat
    import scala.util.Try
    val fmt = DateTimeFormat forPattern "MM/dd/yyyy"
    def validate(date: String) = Try(fmt.parseDateTime(date)).isSuccess
  }