正则表达式验证日期格式dd / mm / yyyy


171

我需要dd/mm/yyyy使用正则表达式验证格式的日期字符串。

此正则表达式验证dd/mm/yyyy,但无效日期无效,例如31/02/4500

^(0?[1-9]|[12][0-9]|3[01])[\/\-](0?[1-9]|1[012])[\/\-]\d{4}$

什么是在dd/mm/yyyyleap年支持下验证格式的有效正则表达式?


3
我认为,如果您设定正确的期望值可能会有所帮助,因为此正则表达式实际上并不能正确验证leap年。例如,2013年2月29日没有,但此正则表达式断言这是有效的:regexr.com?346fp
TML

7
为什么使用正则表达式?有更简单(更准确)的方法……
Dan Puzey

2
正则表达式用于匹配模式,不检查数字值。使用正则表达式查找可能的字符串,然后使用您的宿主语言(PHP等)检查其数值。
安迪·莱斯特

3
该答案已添加到“通用验证任务”下的“ 堆栈溢出正则表达式常见问题 ”中。
aliteralmind 2014年

4
@BurhanKhalid:你错了。正则表达式是进行验证的最佳工具,因为HTML5输入具有名为的属性pattern,该属性采用正则表达式,并且浏览器会针对正则表达式自动进行验证,而无需使用任何JavaScript。只需在pattern属性中设置一个正则表达式即可!
2014年

Answers:


328

您粘贴的正则表达式无法正确验证leap年,但一篇文章中有。我修改了它采取dd/mm/yyyydd-mm-yyyydd.mm.yyyy

^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]))\1|(?:(?:29|30)(\/|-|\.)(?:0?[13-9]|1[0-2])\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)0?2\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|-|\.)(?:(?:0?[1-9])|(?:1[0-2]))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$

我在Arun在他的答案以及此处提供的链接中对其进行了一些测试,它似乎有效。

编辑2019年2月14日:我删除了正则表达式中的逗号,该逗号允许日期如下 29-0,-11


9
史诗般的正则表达式!根据格式互换它有多容易?例如yyyy-mm-dd和mm-dd-yyyy。考虑到这一点,我可以尝试理解它,但这超出了我的正则表达式技能。
mrswadge

7
除之外DD/MM/YYYY,此正则表达式还接受DD/MM/YY我不确定这是否是海报的初衷。如果您不希望使用“ YY”,请删除所有可选的?量词。
user1485864

2
@PurveshDesai替换每个0?0,并且还去掉最后一次出现?
Ofir Luzon 2015年

4
@MaraisRossouw,你是正确的,4位数的年份,其实有3 ?应删除:更换所有(?:1[6-9]|[2-9]\d)?(?:1[6-9]|[2-9]\d)
Ofir Luzon

2
顺便说
一句

266

根据我的要求,我已将@Ofir Luzon提供的正则表达式扩展为dd-mmm-YYYY,dd / mmm / YYYY,dd.mmm.YYYY格式。具有相同要求的其他任何人都可以参考此

^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]|(?:Jan|Mar|May|Jul|Aug|Oct|Dec)))\1|(?:(?:29|30)(\/|-|\.)(?:0?[1,3-9]|1[0-2]|(?:Jan|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec))\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)(?:0?2|(?:Feb))\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|-|\.)(?:(?:0?[1-9]|(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep))|(?:1[0-2]|(?:Oct|Nov|Dec)))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$

并在http://regexr.com/39tr1上测试了一些测试用例。

为了更好地理解此正则表达式,请参考以下图片: 在此处输入图片说明


1
是的,您是如何生成它的?:)
Razor 2015年

我使用某个网站在线生成了该图片,现在我也不记得我从中生成此图片的网站了。记得时,我会添加参考:)
Alok Chaudhary 2015年

4
@ user3733831 8888是可能的年份。我希望活到那个年龄。
Dan Nissenbaum '16

1
即使在leap年也很有效。我还添加了对西班牙语短月份名称的支持。
Fer R

2
@AlokChaudhary,该图是使用debuggex.com
Taha BASRI,

69

注意:

您的正则表达式无法使用“ 4和100的倍数,但不是400的倍数”的年份。通过测试的年份不是not年。例如:1900、2100、2200、2300、2500等。换句话说,它将格式为\ d \ d00的所有年份都放在同一of年类别中,这是不正确的。–学习

因此它仅适用于[1901-2099](Whew)😊

dd / MM / yyyy:

检查是否为leap年。1900年至9999年有效。只有dd / MM / yyyy

(^(((0[1-9]|1[0-9]|2[0-8])[\/](0[1-9]|1[012]))|((29|30|31)[\/](0[13578]|1[02]))|((29|30)[\/](0[4,6,9]|11)))[\/](19|[2-9][0-9])\d\d$)|(^29[\/]02[\/](19|[2-9][0-9])(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)$)

7
此答案仅适用于dd / MM / yyyy。因此,是正确的答案。
罗德里戈(Rodrigo)2015年

2
@SylvainB我已修复它
gdZeus 2015年

2
@gdZeus即使两年后也感谢您提供!令人恐惧的是,一个不完整的解决方案已经在这里得到验证了很长时间。
SylvainB 2015年

为了更快,您可以使组不分组。regexr.com/3esom ^(?:(?:(?:( ?: 0 [1-9] | 1 [0-9] | 2 [0-8])[\ /](?: 0 [1- 9] | 1 [012]))|(?:( ?: 29 | 30 | 31)[\ /](?: 0 [13578] | 1 [02]))|(?:( ?: 29 | 30 )[\ /](?: 0 [4,6,9] | 11)))[\ /](?: 19 | [2-9] [0-9])\ d \ d)|(?: 29 [\ /] 02 [\ /](?: 19 | [2-9] [0-9])(?: 00 | 04 | 08 | 12 | 16 | 20 | 24 | 28 | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | 64 | 68 | 72 | 76 | 80 | 84 | 88 | 92 | 96))$
Matt Vukomanovic

我想我发现了一个错误:29/02/2100不存在(2100不是a年),但是仍然被给定的模式接受。
KnorxThieus


12

我怀疑在不知道用户的语言环境何时从儒略历切换到公历的情况下,以下内容将达到预期的准确性。

不管顺序如何,它都可以接受“-”,“ /”或不接受年,月和日之间的分隔符。

MMddyyyy:

^(((0[13-9]|1[012])[-/]?(0[1-9]|[12][0-9]|30)|(0[13578]|1[02])[-/]?31|02[-/]?(0[1-9]|1[0-9]|2[0-8]))[-/]?[0-9]{4}|02[-/]?29[-/]?([0-9]{2}(([2468][048]|[02468][48])|[13579][26])|([13579][26]|[02468][048]|0[0-9]|1[0-6])00))$

ddMMyyyy:

^(((0[1-9]|[12][0-9]|30)[-/]?(0[13-9]|1[012])|31[-/]?(0[13578]|1[02])|(0[1-9]|1[0-9]|2[0-8])[-/]?02)[-/]?[0-9]{4}|29[-/]?02[-/]?([0-9]{2}(([2468][048]|[02468][48])|[13579][26])|([13579][26]|[02468][048]|0[0-9]|1[0-6])00))$

yyyyMMdd:

^([0-9]{4}[-/]?((0[13-9]|1[012])[-/]?(0[1-9]|[12][0-9]|30)|(0[13578]|1[02])[-/]?31|02[-/]?(0[1-9]|1[0-9]|2[0-8]))|([0-9]{2}(([2468][048]|[02468][48])|[13579][26])|([13579][26]|[02468][048]|0[0-9]|1[0-6])00)[-/]?02[-/]?29)$

除订单外,所有这些都适用于儒略历(每四年le年)直到1700年(公历从儒略偏离)。它有两个问题:

  1. 它接受年份0000,这在很多(但不是全部)标准中不存在。请注意,ISO 8601确实接受0000年(相当于1 BCE)。
  2. 它不会跳过公历使用时丢失的10-13天。但是,这因地区而异。例如,罗马天主教会从1582年10月5日至10月14日跳过了10天,而希腊(最后一个转换)则在1923年2月16日至1928年28日跳过了13天,这要考虑到1700年的leap年, 1800和1900。

已针对Java的从0001年到9999年的日历实现进行了测试,唯一的差异是上述1582年的10天。


YYYYMMDD正则表达式与[01 | 02 | 03 | 05 | 06 | 07 | 09 | 10 | 11 | 13 | 14 | 15] 00-02-29错误匹配。更正的正则表达式:^([0-9]{4}[-/]?((0[13-9]|1[012])[-/]?(0[1-9]|[12][0-9]|30)|(0[13578]|1[02])[-/]?31|02[-/]?(0[1-9]|1[0-9]|2[0-8]))|([0-9]{2}(([2468][048]|[02468][48])|[13579][26])|([13579][26]|[02468][048])00)[-/]?02[-/]?29)$。使用python测试:repl.it/repls/DependentBestChapters
kpr

10

对于那些看了这些并且完全感到困惑的人,这是我脚本的摘录。不幸的是,它所做的只是在日期时间输入中匹配有效数字,并且2月31日将被标记为有效,但是正如许多人所说的,regex确实不是进行此测试的最佳工具。

以'yyyy-MM-dd hh:mm'格式匹配日期(或者您可以按任意顺序匹配)

var dateerrors = false;
var yearReg = '(201[4-9]|202[0-9])';            ///< Allows a number between 2014 and 2029
var monthReg = '(0[1-9]|1[0-2])';               ///< Allows a number between 00 and 12
var dayReg = '(0[1-9]|1[0-9]|2[0-9]|3[0-1])';   ///< Allows a number between 00 and 31
var hourReg = '([0-1][0-9]|2[0-3])';            ///< Allows a number between 00 and 24
var minReg = '([0-5][0-9])';                    ///< Allows a number between 00 and 59
var reg = new RegExp('^' + yearReg + '-' + monthReg + '-' + dayReg + ' ' + hourReg + ':' + minReg + '$', 'g');
$('input').filter(function () {return this.id.match(/myhtml_element_with_id_\d+_datetime/);}).each(function (e) {
    if (e > 0) {
        // Don't test the first input. This will use the default
        var val = $(this).val();
        if (val && !val.trim().match(reg)) {
            dateerrors = true;
            return false;
        }
    }
});
if (dateerrors) {
    alert('You must enter a validate date in the format "yyyy-mm-dd HH:MM", e.g. 2019-12-31 19:30');
    return false;
}

上面的脚本通过构建正则表达式对象开始。然后,找到其ID匹配特定模式的所有输入,然后循环遍历这些输入。我没有测试找到的第一个输入(if (e > 0))。

一点解释:

var reg = new RegExp('^' + yearReg + '-' + monthReg + '-' + dayReg + ' ' + hourReg + ':' + minReg + '$', 'g');

^表示比赛开始,而$表示比赛结束。

return this.id.match(/myhtml_element_with_id_\d+_datetime/);

\d+表示匹配单个或连续的整数序列,所以myhtml_element_with_id_56_datetimemyhtml_element_with_id_2_datetime将匹配,但myhtml_element_with_id_5a_datetime不会匹配


8

这是正则表达式的另一个版本,可匹配以下任何一种日期格式,并允许省略前导零:

正则表达式: ^[0-3]?[0-9].[0-3]?[0-9].(?:[0-9]{2})?[0-9]{2}$

火柴:

1/1/11 or 1.1.11 or 1-1-11 : true 01/01/11 or 01.01.11 or 01-01-11 : true 01/01/2011 or 01.01.2011 or 01-01-2011 : true 01/1/2011 or 01.1.2011 or 01-1-2011 : true 1/11/2011 or 1.11.2011 or 1-11-2011 : true 1/11/11 or 1.11.11 or 1-11-11 : true 11/1/11 or 11.1.11 or 11-1-11 : true

正则表达式可视化

Debuggex演示


4
如果您具有13/13/2000= 匹配项
不起作用

3
39/39/39不是日期。请停止对此答案投票。
沃伦·塞金特

6

在这里,我写了一个dd/mm/yyyy分隔符可以是-.,/一年范围之一的表达式0000-9999

它处理leap年,并针对正则表达式风格设计,支持先行,捕获组和反向引用。不适用于,例如d/m/yyyy。如果需要,请添加其他分隔符[-.,/]

^(?=\d{2}([-.,\/])\d{2}\1\d{4}$)(?:0[1-9]|1\d|[2][0-8]|29(?!.02.(?!(?!(?:[02468][1-35-79]|[13579][0-13-57-9])00)\d{2}(?:[02468][048]|[13579][26])))|30(?!.02)|31(?=.(?:0[13578]|10|12))).(?:0[1-9]|1[012]).\d{4}$

在regex101上测试;作为Java字符串:

"^(?=\\d{2}([-.,\\/])\\d{2}\\1\\d{4}$)(?:0[1-9]|1\\d|[2][0-8]|29(?!.02.(?!(?!(?:[02468][1-35-79]|[13579][0-13-57-9])00)\\d{2}(?:[02468][048]|[13579][26])))|30(?!.02)|31(?=.(?:0[13578]|10|12))).(?:0[1-9]|1[012]).\\d{4}$"

解释:

(?x) # modifier x: free spacing mode (for comments)
     # verify date dd/mm/yyyy; possible separators: -.,/
     # valid year range: 0000-9999

^    # start anchor

# precheck xx-xx-xxxx,... add new separators here
(?=\d{2}([-.,\/])\d{2}\1\d{4}$)

(?:  # day-check: non caturing group

  # days 01-28
  0[1-9]|1\d|[2][0-8]| 

  # february 29d check for leap year: all 4y / 00 years: only each 400
  # 0400,0800,1200,1600,2000,...
  29
  (?!.02. # not if feb: if not ...
    (?!
      # 00 years: exclude !0 %400 years
      (?!(?:[02468][1-35-79]|[13579][0-13-57-9])00)

      # 00,04,08,12,... 
      \d{2}(?:[02468][048]|[13579][26])
    )
  )|

  # d30 negative lookahead: february cannot have 30 days
  30(?!.02)|

  # d31 positive lookahead: month up to 31 days
  31(?=.(?:0[13578]|10|12))

) # eof day-check

# month 01-12
.(?:0[1-9]|1[012])

# year 0000-9999
.\d{4}

$ # end anchor

另请参阅SO Regex常见问题解答;如果失败,请通知我。


5

在这里找到此reg ex

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

这样mm/dd/yyyy可以正确验证格式和有效日期(但不能验证m/d/yyyy)。

一些测试


1
仅在2014年之前可以使用,必须将| 20(0 [0-9] | 1 [0-4])))更改为| 20(0 [0-9] | 1 [0-9])))以支持,直到2019年
Tony Dong

5
"^(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.]((19|20)\\d\\d)$"

将验证之间的任何日期 1900-2099


5

以下表达式很好并且易于操作:

((((0[13578]|1[02])(\/|-|.)(0[1-9]|1[0-9]|2[0-9]|3[01]))|((0[469]|11)(\/|-|.)(0[1-9]|1[0-9]|2[0-9]|3[0]))|((02)((\/|-|.)(0[1-9]|1[0-9]|2[0-8]))))(\/|-|.)(19([6-9][0-9])|20(0[0-9]|1[0-4])))|((02)(\/|-|.)(29)(\/|-|.)(19(6[048]|7[26]|8[048]|9[26])|20(0[048]|1[26])))

它根据MM / dd / YYYY格式进行验证,并允许从1960年到2016年的leap年支持。如果需要扩展的leap年支持,则只需操纵表达式的以下部分:

(19(6[048]|7[26]|8[048]|9[26])|20(0[048]|1[26]))

希望这对您有帮助


3

另一个根据日期(mm)和年份(yyyy)验证日期(dd)的答案(即,还验证leap年2月29日),并允许年份范围从0001到9999(根据格里高利标准,在无效年份中为0000)日历)

^(?:(?:(?:0[1-9]|[12]\d|3[01])/(?:0[13578]|1[02])|(?:0[1-9]|[12]\d|30)/(?:0[469]|11)|(?:0[1-9]|1\d|2[0-8])/02)/(?!0000)\d{4}|(?:(?:0[1-9]|[12]\d)/02/(?:(?!0000)(?:[02468][048]|[13579][26])00|(?!..00)\d{2}(?:[02468][048]|[13579][26]))))$

1
无法验证18/05/0017

1

我正在使用接受MM / DD / YYYY格式的API 。我找不到与Ofir的回答一样能飞跃多年的其他帖子,因此我对其进行了调整,然后将其重新发布在这里,以供可能需要的人使用。

/^(?:(?:(?:0[13578]|1[02])(\/)31)\1|(?:(?:0[1,3-9]|1[0-2])(\/)(?:29|30)\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:02(\/)29\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:(?:0?[1-9])|(?:1[0-2]))(\/)(?:0[1-9]|1\d|2[0-8])\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$/

0
((((0[13578]|1[02])\/(0[1-9]|1[0-9]|2[0-9]|3[01]))|((0[469]|11)\/(0[1-9]|1[0-9]|2[0-9]|3[0]))|((02)(\/(0[1-9]|1[0-9]|2[0-8]))))\/(19([6-9][0-9])|20([0-9][0-9])))|((02)\/(29)\/(19(6[048]|7[26]|8[048]|9[26])|20(0[048]|1[26]|2[048])))

将验证MM/DD/YYYY格式1960,以2028

如果您需要扩展leap年支持,请添加

19(6[048]|7[26]|8[048]|9[26])|20(0[048]|1[26]|2[048]|3[26]|4[048])))

这也是工作

^((((0[13578]|1[02])[/](0[1-9]|1[0-9]|2[0-9]|3[01]))|((0[469]|11)[/](0[1-9]|1[0-9]|2[0-9]|3[0]))|((02)([/](0[1-9]|1[0-9]|2[0-8]))))[/](19([6-9][0-9])|20([0-9][0-9])))|((02)[/](29)[/](19(6[048]|7[26]|8[048]|9[26])|20(0[048]|1[26]|2[048])))

如果您可以更改格式而mm-dd-yyyy不是替换[/][-] 也可以在线查看http://regexr.com/


0

对于日期MM / DD / YYYY,您可以使用

^((((0[13578])|([13578])|(1[02]))[\/](([1-9])|([0-2][0-9])|(3[01])))|(((0[469])|([469])|(11))[\/](([1-9])|([0-2][0-9])|(30)))|((2|02)[\/](([1-9])|([0-2][0-9]))))[\/]\d{4}$|^\d{4}$

它会验证正确的日期和飞蛾。

请记住,您可以在以下位置检查正则表达式

regex101

我建议:)

玩得开心!


0
^(((([13578]|0[13578]|1[02])[-](0[1-9]|[1-9]|1[0-9]|2[0-9]|3[01]))|(([469]|0[469]|11)[-]([1-9]|1[0-9]|2[0-9]|3[0]))|((2|02)([-](0[1-9]|1[0-9]|2[0-8]))))[-](19([6-9][0-9])|20([0-9][0-9])))|((02)[-](29)[-](19(6[048]|7[26]|8[048]|9[26])|20(0[048]|1[26]|2[048])))

此正则表达式将以以下格式验证日期:

12-30-2016(mm-dd-yyyy)或12-3-2016(mm-d-yyyyy)或1-3-2016(md-yyyyy)或1-30-2016(m-dd-yyyyy)


0

我知道这是问题的切线答案,但是如果问题的目的是“我如何验证日期?”,那么为什么不尝试让编程语言来完成所有艰苦的工作(如果您使用的语言是能够)?

例如在PHP

$this_date_object = date_create($this_date);

if ($this_date_object == false )
    {

        // process the error

    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.