gpt4 book ai didi

javascript - 尝试验证 YYYY/MM/dd

转载 作者:行者123 更新时间:2023-11-29 17:05:23 26 4
gpt4 key购买 nike

我知道那里有很多正则表达式线程,但我找不到任何地方。

我有一个适用于 DD/MM/YYYY 格式的正则表达式。在这里:

^((0?[13578]|1[02])[\/.]31[\/.][1-9][0-9]{3})|(([01,1]|0[3-9]|1[1-2])[\/.](29|30)[\/.][1-9][0-9]{3})|((0?[1-9]|1[0-2])[\/.](0?[1-9]|1[0-9]|2[0-8])[\/.][1-9][0-9]{3})|([02,2][\/.]29[\/.](([1-9][0-9](04|08|[2468][048]|[13579][26]))|([2468][0]{3})))$

示例:29/2/2014、31/4/2014...

但是当我尝试使用 YYYY/MM/DD 格式进行验证时,我发现了这个:

^(((19|20)([2468][048]|[13579][26]|0[48])|2000)[\/.]02[\/.]29|((19|20)[0-9]{2}[\/.](0?[469]|11)[\/.](0?[1-9]|[12][0-9]|30)|(19|20)[0-9]{2}[\/.](0?[13578]|1[02])[\/.](0?[1-9]|[12][0-9]|3[01])|(19|20)[0-9]{2}[\/.]02[\/.](0?[1-9]|1[0-9]|2[0-8])))$

此模式仅适用于 YYYY 从:19xx -> 20xxx。

当我更改它时,我希望它可以很好地与 YYYY 从:1xxx ->9xxx 一起使用。但效果并不好。

我是正则表达式的新手,很难逃脱它。

非常感谢,抱歉我的英语不好。

最佳答案

TL;DR Minitech 的评论和 TheQ 的评论是正确的——这对于正则表达式来说不是一项伟大的任务。下面给出了一个非正则表达式的解决方案。只是为了好玩,一个可怕的正则表达式也是如此。

编辑:我决定在午餐时花几分钟时间清理它并添加“正确”的方法(没有正则表达式)以及一个 jsFiddle。


真正的答案

为了可读性、可维护性和健全性,正确的做法是避免在此处使用正则表达式。编写正则表达式来执行此操作非常困难,而且结果也非常难以阅读。

相反,只需将日期解析为其组成部分,然后像这样验证它们:

/**
* Check whether a given year is a leap year
* @param integer y The integer
* @return boolean True for yes, false for no
*/
function isLeapYear(y) {
return (0 == y % 4 && (0 == y % 400 || 0 != y % 100));
}

/**
* Validate a date in YYYY/MM/DD format (allows YYYY/M/D and periods instead of slashes) without regex.
* @param string str The date to test.
* @return boolean True for valid, false for invalid.
*/
function validateDateWithoutRegex(str) {
// check the format first
if(!/^\d{4}[\/.]\d{1,2}[\/.]\d{1,2}$/.test(str)) {
return false;
}
var parts = str.split(/\D/) // split on non-digits
.map(function(val) { return parseInt(val); }); // convert strings to ints
if(parts[0] < 1000 || parts[0] > 2999) { // invalid year
return false;
}
if(parts[1] > 12 || parts[1] === 0) { // invalid month
return false;
}
if(parts[2] > 31 || parts[2] === 0) { // invalid day
return false;
}
switch(parts[1]) {
case 4:
case 6:
case 9:
case 11:
if(parts[2] > 30) { // invalid day
return false;
}
break;
case 2: // February...
return (parts[2] < 29 || parts[2] == 29 && isLeapYear(parts[0]));
break;
}
return true;
}

// Usage: validateDateWithoutRegex('2014/07/28'); // returns true

完全疯狂的正则表达式答案

但是,只是因为今晚我想做一些正则表达式......你可以使用这个怪物:

/^(?=(?!\d+\D0?2\D29)|(?:\d{2}(?:04|08|[13579][26]|[2468][048])|1[26]00|2000)\D0?2\D29$)([12]\d{3})[\/.]((?:0?[13578]|10|12)[\/.](?:0?[1-9]|[12]\d|3[0-1])|(?:0?[469]|11)[\/.](?:0?[1-9]|[12]\d|30)|0?2[\/.](?:0?[1-9]|1\d|2[0-9]))$/

这甚至可以验证闰年。

Here's an interactive jsFiddle that also runs 50+ unit tests验证此方法与非正则表达式方法的工作方式相同。

here's a Regex101 DEMO

可能有用的解释,由 Debuggex 提供:

Regular expression visualization

Debuggex Demo

匹配示例:

  • 2014/12/31
  • 1937/4/17
  • 1066/1/4
  • 1066/2/28
  • 2014/1/1
  • 2012/02/29
  • 2000/02/29(400 的倍数为闰年)
  • 1600/02/29(400 的倍数为闰年)
  • 2015/01/01

不匹配示例:

  • 1900/02/29(不是 400 的倍数的 100 的倍数不是闰年)
  • 2012/02/30
  • 2012/00/01
  • 2012/00/00
  • 2012/04/31
  • 2012/17/01
  • 2012/02/00
  • 1066/1/4444
  • 1066/2/29
  • 1065/2/29
  • 2014/14/1
  • 2014/02/29

已经很晚了,我们将不胜感激。

关于两种方法的历史问题的注释

公历与新教改革等历史密切相关。它在创建时引起了极大的争议,并没有被普遍采用。采用它的地方在不同时间以不同方式采用它。结果:哪些日期在公历中有效取决于您所在的位置。 See, e.g., Wikipedia .

从本质上讲,公历于 1582 年问世。从那时起,其采用因国家/地区而异。例如,日历基本上定义为 1582 年的 10 月 5 日至 14 日不存在。许多国家同样跳过日期以移动旧的(Julian)日历日期以匹配公历,但他们并没有全部跳过相同的日子(甚至天数相同);他们跳过哪几天取决于国家/地区以及采用日历的时间。

因此,如果您希望能够验证 1582 年之前(在某些地方甚至是 1923 年)之前的日期,请牢记所有这些。玩得开心!

关于javascript - 尝试验证 YYYY/MM/dd,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24989065/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com