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

发布于 2024-11-07 01:15:47 字数 161 浏览 1 评论 0原文

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

我怎样才能在scala中为此编写正则表达式检查?我看过模式匹配示例 - 但这似乎过于复杂。

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

I have a date input box in my lift application, and I want to check that a user-entered date is in correct format: dd/mm/yyyy.

How can I write a regex check for this in scala? I've looked at pattern matching examples - but that seems over-complicated.

PS: I don't have to use regex, any other alternatives are welcome!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

不即不离 2024-11-14 01:15:47

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

UPDATE

要使用 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)
)

SimpleDateFormat is ugly and (more disturbingly) non-thread-safe. If you try to simultaneously use the same instance in 2 or more threads then expect things to blow up in a most unpleasant fashion.

JodaTime is far nicer:

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

If it throws an IllegalArgumentException, then the date wasn't valid.

As I suspect you'll want to know the actual date if it was valid, you may want to return an Option[DateTime], with None if it was invalid.

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

Alternatively, use an Either to capture the actual exception if formatting wasn't possible:

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

UPDATE

To then use the Either, you have two main tactics:

map one of the two sides:

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

fold it:

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

Of course, the two can be composed:

parseDate(input).left map (_.getMessage) fold (
  errMsg => S.error("birthdate", errMsg), //if failure (Left by convention)
  dt => successFunc(dt) //if success (Right by convention)
)
三人与歌 2024-11-14 01:15:47

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

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
  }

As user unknown has written you should use some library that knows how to handle dates correctly including days per specific month and leap years.

SimpleDateFormat is not very intuitive regarding rollovers of fields and initially accepts wrong dates by just rolling over the other fields. To prevent it from doing so you have to invoke setLenient(false) on it. Also keep in mind that SimpleDateFormat is not thread-safe so you need to create a new instance every time you want to use it:

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

Alternatively you may also use Joda Time which is a bit more intuitive than the Java Date APIs and offers thread-safe date formats:

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

def validate(date: String) = try {
    format.parseMillis(date)
    true
  }
  catch {
    case e: IllegalArgumentException => false
  }
聆听风音 2024-11-14 01:15:47

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

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

It's a good practice to define the DateTimeFormatter instance in an object since it's thread-safe and immutable.

  object DateOfBirth{
    import org.joda.time.format.DateTimeFormat
    import scala.util.Try
    private val fmt = DateTimeFormat.forPattern("MM/dd/yyyy")
    def validate(date: String) = Try(fmt.parseDateTime(date)).isSuccess
  }
夜还是长夜 2024-11-14 01:15:47

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

处理允许 28 和 30 作为日期(但不允许 38)、不同的月份长度和闰年的正则表达式可能是一个有趣的挑战,但对于现实世界的代码而言并非如此。

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

(我假设 M 代表大月,而不是 m 代表小分钟)。

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

scala> df.parse ("09/13/2001")                                
res255: java.util.Date = Wed Jan 09 00:00:00 CET 2002

hoppla - 它非常宽容,并且可以延续几个月到下一年。但我们可以通过第二个格式化过程来获取它:

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

我希望您不受正则表达式的束缚,并且可以使用它。

I wouldn't use a regex, but SimpleDateFormat (which isn't that simple, as we will see).

A regular expression which handles to allow 28 and 30 as day, but not 38, different month-lengths and leap years, might be an interesting challenge, but not for real world code.

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

(I assume M as in big Month, not m as in small minute).

Now, let's start with an error:

scala> df.parse ("09/13/2001")                                
res255: java.util.Date = Wed Jan 09 00:00:00 CET 2002

hoppla - it is very tolerant, and wraps months around to the next year. But we can get it with a second formatting process:

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

I hope you aren't bound to regex, and can use it.

一人独醉 2024-11-14 01:15:47

由此我们可以验证字符串中的日期,并通过解析“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
    }

from this we can validate date in string as well as we get the expected date response by parsing in the format like "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
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文