用于检查日期的PHP正则表达式为YYYY-MM-DD格式

问题描述 投票:81回答:20

我正在尝试检查最终用户输入的日期是否在YYYY-MM-DD中。正则表达式从来都不是我的强项,对于设置的preg_match(),我总是收到错误的返回值。

所以我假设我把正则表达式弄乱了,下面将详细介绍。

$date="2012-09-12";

if (preg_match("^[0-9]{4}-[0-1][0-9]-[0-3][0-9]$",$date))
    {
        return true;
    }else{
        return false;
    }

有什么想法吗?

php regex date-format
20个回答
174
投票

尝试一下。

$date="2012-09-12";

if (preg_match("/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/",$date)) {
    return true;
} else {
    return false;
}

2
投票
您也可以这样:

1
投票
如果要匹配该类型的日期,请使用:

1
投票
这应该告诉您格式是否有效以及输入日期是否有效。

1
投票
在一行语句中检查并确认if (DateTime::createFromFormat('Y-m-d', $date)->format('Y-m-d') === $date) { // date is correctly formatted and valid, execute some code } 日期

1
投票
如果有帮助,这里是用于j-n-Y格式的正则表达式(年份必须大于2018):

0
投票
这完全取决于您希望此功能的严格程度。例如,如果您不想允许大于12的月份和大于31的日子(不取决于月份,则需要编写日期逻辑),则可能会变得非常复杂:

0
投票
要在php中使用日期,您应遵循php标准,以便给定的正则表达式可确保您具有可以与PHP一起使用的有效日期。

0
投票
此方法可用于验证PHP中的日期。当前方法适用于mm / dd / yyyy格式。您必须按照if (preg_match('/^([1-9]|[1-2][0-9]|[3][0-1])\-([1-9]|[1][0-2])\-(?:20)([1][8-9]|[2-9][0-9])$/', $date)) { // Do stuff } 中的格式和定界符更新function checkDate($date) { $regex = '/^' . '(' . // Allows years 0000-9999 '(?:[0-9]{4})' . '\-' . // Allows 01-12 '(?:' . '(?:01)|(?:02)|(?:03)|(?:04)|(?:05)|(?:06)|(?:07)|(?:08)|(?:09)|(?:10)|' . '(?:11)|(?:12)' . ')' . '\-' . // Allows 01-31 '(?:' . '(?:01)|(?:02)|(?:03)|(?:04)|(?:05)|(?:06)|(?:07)|(?:08)|(?:09)|(?:10)|' . '(?:11)|(?:12)|(?:13)|(?:14)|(?:15)|(?:16)|(?:17)|(?:18)|(?:19)|(?:20)|' . '(?:21)|(?:22)|(?:23)|(?:24)|(?:25)|(?:26)|(?:27)|(?:28)|(?:29)|(?:30)|' . '(?:31)' . ')' . '$/'; if ( preg_match($regex, $date) ) { return true; } return false; } $result = checkDate('2012-09-12'); 中的参数序列。

0
投票
[[如果您使用Symfony 4.1.2,请尝试此] [1]

0
投票
来自Laravel 5.7和日期格式,即:12/31/2019

87
投票

为此最好使用其他机制。

现代解决方案,带有DateTime

DateTime

这也验证了输入:$dt = DateTime::createFromFormat("Y-m-d", $date); return $dt !== false && !array_sum($dt::getLastErrors()); 确保可以使用指定的格式解析日期,并且$dt !== false技巧是确保PHP不进行“月度移位”的简洁方法(例如,考虑1月32日为2月1日)。有关更多信息,请参见array_sum

DateTime::getLastErrors()DateTime::getLastErrors()的旧式解:

explode

这也验证了输入也是一个有效日期。您当然可以使用正则表达式来做到这一点,但这会大惊小怪-2月29日根本无法使用正则表达式进行验证。

这种方法的缺点是,您必须非常小心地拒绝所有可能的“不良”输入,而在任何情况下都不会发出通知。方法如下:

  • [explode仅限返回3个令牌(因此,如果输入为“ 1-2-3-4”,则checkdate将变为“ 3-4”)]
  • checkdate用于确保输入不包含任何非数字字符(破折号除外)
  • list($y, $m, $d) = array_pad(explode('-', $date, 3), 3, 0); return ctype_digit("$y$m$d") && checkdate($m, $d, $y); (具有将导致explode失败的默认值)以确保返回了足够的元素,以便如果输入为“ 1-2”,则$d将不会发出通知

0
投票
格式1:$ format1 =“ 2012-12-31”;

38
投票

yyyy-mm-dd:ctype_digit

yyyy / mm / dd:

array_pad

mm-dd-yyyy:

checkdate

mm / dd / yyyy:

list()

dd / mm / yyyy:

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

dd-mm-yyyy:

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

34
投票

标准:

每年被4整除的年份是a年,除非它可以被100整除,除非可以被400整除。因此:

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

2月Fe年有29天,非not年有28天

4月,6月,9月和11月的30天

[一月,三月,五月,七月,八月,十月和十二月的31天

测试:

以下日期均应通过验证:

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

以下日期均应通过验证:

/^(((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))))$/g

范围:

我们将测试1000年1月1日至2999年12月31日之间的日期。

技术上,目前使用的公历仅在1753年用于大英帝国,并在1600年代分别用于欧洲国家,但我我不会为此担心。

正则表达式测试test年:

可被400整除的年份:

/^(((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))))$/g

年份可被4整除:

2004 - leap year - divisible by 4 1900 - not a leap year - divisible by 4, but also divisible by 100 2000 - leap year - divisible by 4, also divisible by 100, but divisible by 400

年份可被100整除:

1976-02-29 2000-02-29 2004-02-29 1999-01-31

不可被100整除:

2015-02-29 2015-04-31 1900-02-29 1999-01-32 2015-02-00

年份可被100整除而不是400:

1200|1600|2000|2400|2800 can be shortened to: (1[26]|2[048])00 if you wanted all years from 1AD to 9999 then this would do it: (0[48]|[13579][26]|[2468][048])00 if you're happy with accepting 0000 as a valid year then it can be shortened: ([13579][26]|[02468][048])00

可除以4,但不能除以100:

[12]\d([02468][048]|[13579][26])

The年:

[12]\d00

无法被4整除:

[12]\d([1-9]\d|\d[1-9])

不是a年:

((1[1345789])|(2[1235679]))00

有效月份和月份,不包括二月(MM-DD):

[12]\d([2468][048]|[13579][26]|0[48])
[2月28天:

divisible by 400 or (divisible by 4 and not divisible by 100) ((1[26]|2[048])00)|[12]\d([2468][048]|[13579][26]|0[48])

2月,共29天:

[12]\d([02468][1235679]|[13579][01345789])

有效日期:

Not divisible by 4 OR is divisible by 100 but not by 400 ([12]\d([02468][1235679]|[13579][01345789]))|(((1[1345789])|(2[1235679]))00)
因此,您拥有一个正则表达式,用于YYYY-MM-DD格式的1000年1月1日至2999年12月31日之间的日期。

我怀疑它可以缩短很多,但我会把它留给别人。

将匹配所有有效日期。如果您只希望它仅包含一个日期而没有其他任何内容时才有效,则将其包装在((01|03|05|07|08|10|12)-(0[1-9]|[12]\d|3[01]))|((04|06|09|11)-(0[1-9]|[12]\d|30)) shortened to: ((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)) 中,如下所示:

02-(0[1-9]|1\d|2[0-8])

如果要在可选日期输入中输入它(例如,可以为空白或有效日期),请在开头添加02-(0[1-9]|[12]\d)
,如下所示:

(leap year followed by (valid month-day-excluding-february OR 29-day-february)) OR (non leap year followed by (valid month-day-excluding-february OR 28-day-february)) ((((1[26]|2[048])00)|[12]\d([2468][048]|[13579][26]|0[48]))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|[12]\d))))|((([12]\d([02468][1235679]|[13579][01345789]))|((1[1345789]|2[1235679])00))-((((0[13578]|1[02])-(0[1-9]|[12]\d|3[01]))|((0[469]|11)-(0[1-9]|[12]\d|30)))|(02-(0[1-9]|1\d|2[0-8]))))


16
投票
您可以这样操作:

7
投票
您可以将preg_match与checkdate php函数一起使用

6
投票
我知道这是一个老问题。但我认为我有一个好的解决方案。

4
投票
preg_match需要一个/或另一个字符作为分隔符。

3
投票
您可以使用
© www.soinside.com 2019 - 2024. All rights reserved.