2

到目前为止,这是我的正则表达式

/^((((0?[1-9]|[12]\d|3[01])[\-\/](0?[13578]|1[02])[\-\/]((1[6-9]|[2-9]\d)?\d{2}))|((0?[1-9]|[12]\d|30)[\-\/](0?[13456789]|1[012])[\-\/]((1[6-9]|[2-9]\d)?\d{2}))|((0?[1-9]|1\d|2[0-8])[\-\/]0?2[\-\/]((1[6-9]|[2-9]\d)?\d{2}))|(29[\-\/]0?2[\-\/]((1[6-9]|[2-9]\d)?(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00)|00)))|(((0[1-9]|[12]\d|3[01])(0[13578]|1[02])((1[6-9]|[2-9]\d)?\d{2}))|((0[1-9]|[12]\d|30)(0[13456789]|1[012])((1[6-9]|[2-9]\d)?\d{2}))|((0[1-9]|1\d|2[0-8])02((1[6-9]|[2-9]\d)?\d{2}))|(2902((1[6-9]|[2-9]\d)?(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00)|00))))$/i

它可以完美地进行日期验证,包括闰年,但它接受的格式是 dd-mm-yyyy,我想要 mm-dd-yyyy。它还接受我不想要的年份的两位数。

4

3 回答 3

3

从示例开发复杂正则表达式的最简单方法是使用http://txt2re.com上的正则表达式生成器

于 2013-03-31T21:10:53.297 回答
2

// 您可以投反对票或将其标记为“不是答案”,但我无法抗拒发布此...

天哪,你为什么这么讨厌自己?

正则表达式是一个强大而有用的工具,但它并不能解决这个世界上的所有问题。我一遍又一遍地看到解析日期的尝试——尊重闰年,或使用正则表达式解析 XML/HTML。

这是错误的。

您的正则表达式不可读且不可维护(您已通过此问题证明了这一点)。构建这样的怪物正则表达式作为练习可能会很好,但您甚至不应该考虑在生产环境中使用它。

原因是(仅举几例!):

  • 正确性:您不确定这是否有效。您将花费数小时来分析和测试它。

  • 性能:这样大小的正则表达式可能需要很长时间才能执行。

  • 错误输出:正则表达式只为您提供“匹配/不匹配”结果。您没有机会告诉用户他输入的日期在语法上是无效的还是今年不存在 2 月 29 日

学会为特定目的选择合适的工具。不存在通用的“我可以做所有事情”的工具。

于 2013-03-31T21:45:46.947 回答
1

哇。我真的怀疑一个正则表达式是去这里的方式......但是,让我们尝试一下。

首先重新格式化正则表达式以使其更具可读性。如您所见,它由许多替代方案组成。添加评论:

/^
 (
  (
   ((0?[1-9]|[12]\d|3[01])-/-/)    # dd-/-/
   |
   ((0?[1-9]|[12]\d|30)-/-/)       # dd-/-/ (uh, this seems redundant?)
   |
   ((0?[1-9]|1\d|2[0-8])[-/]0?2-/) # dd-/-/ (february)
   |
   (29[-/]0?2-/)
  )
  |
  (
   (
    (0[1-9]|[12]\d|3[01])     # day
    (0[13578]|1[02])          # month
    ((1[6-9]|[2-9]\d)?\d{2})  # year
   )
   |
   (
    (0[1-9]|[12]\d|30)        # day
    (0[13456789]|1[012])      # month
    ((1[6-9]|[2-9]\d)?\d{2})  # year
   )
   |
   (
    (0[1-9]|1\d|2[0-8])       # day
    02                        # month
    ((1[6-9]|[2-9]\d)?\d{2})  # year
   )
   |
   (
    2902                      # day and month
    (                         # year in which there's a 29-02-xxxx
     (1[6-9]|[2-9]\d)?
     (0[48]|[2468][048]|[13579][26])
     |
     ((16|[2468][048]|[3579][26])00)
     |
     00
    )
   )
  )
 )
$/i

接下来,重新排序正则表达式以将其从 ddmmyyyy 更改为 mmddyyyy:

/^
 (
  (
   (-/(0?[1-9]|[12]\d|3[01])-/)    # -/dd-/
   |
   (-/(0?[1-9]|[12]\d|30)-/)       # -/dd-/ (uh, this seems redundant?)
   |
   ([-/]0?2(0?[1-9]|1\d|2[0-8])-/) # -/dd-/ (february) (I don't really get this one...)
   |
   ([-/]0?229-/) # really confused... what kind of date format is this?
  )
  |
  (
   (
    (0[13578]|1[02])          # month
    (0[1-9]|[12]\d|3[01])     # day
    ((1[6-9]|[2-9]\d)?\d{2})  # year
   )
   |
   (
    (0[13456789]|1[012])      # month
    (0[1-9]|[12]\d|30)        # day
    ((1[6-9]|[2-9]\d)?\d{2})  # year
   )
   |
   (
    02                        # month
    (0[1-9]|1\d|2[0-8])       # day
    ((1[6-9]|[2-9]\d)?\d{2})  # year
   )
   |
   (
    0229                      # day and month
    (                         # year in which there's a 29-02-xxxx
     (1[6-9]|[2-9]\d)?
     (0[48]|[2468][048]|[13579][26])
     |
     ((16|[2468][048]|[3579][26])00)
     |
     00
    )
   )
  )
 )
$/i

请注意,我对包含的日期格式感到非常困惑,-/因此可能无法正确重写它们。

然后将其放入您的代码中。如果您不希望有人死于致命剂量的不可读的正则表达式,请保留注释(如果您的编程语言允许这样做)。

于 2013-03-31T21:38:31.863 回答