I am trying to make a date regex validator. The issue I'm having is that I'm using an input field with "date"
type, which works like a charm in Chrome; it opens a calendar-like in Chrome, but in the rest it does nothing, so I decided to go for a manual input of the date for the rest.
我正在尝试制作一个日期正则表达式验证器。我遇到的问题是我使用的是带有“日期”类型的输入字段,它就像Chrome中的魅力一样;它在Chrome中打开了一个日历,但在其余部分它什么也没做,所以我决定手动输入其余的日期。
This is my error throwing message (I'm looking for YYYY-MM-DD format):
这是我的错误抛出消息(我正在寻找YYYY-MM-DD格式):
$date_regex ='#^(19|20)\d\d[\- /.](0[1-9]|1[012])[\- /.](0[1-9]|[12][0-9]|3[01])$#';
$hiredate = $_POST['hiredate'];
if (!preg_match($date_regex, $hiredate)){
$errors[] = 'Your hire date entry does not match the YYYY-MM-DD required format.';
}
I know there are a lot of examples about this, but I tried like 20 already and I couldn't solve it. Maybe I'm missing something.
我知道有很多这方面的例子,但我已经尝试了20个,我无法解决它。也许我错过了一些东西。
Here's the input field, if somewhat relevant:
这是输入字段,如果有些相关:
<input type="date" name="hiredate" />
3 个解决方案
#1
10
Your regex didn't work because you had unescaped /
delimiter.
你的正则表达式没有用,因为你有未转义/分隔符。
The regex that would validate date in format YYYY-MM-DD
as follows:
将以YYYY-MM-DD格式验证日期的正则表达式如下:
^(19|20)\d\d[\-\/.](0[1-9]|1[012])[\-\/.](0[1-9]|[12][0-9]|3[01])$
It will validate that the year starts with 19
or 20
, that the month is not greater than 12
and doesn't equal 0
and that the day is not greater than 31
and doesn't equal 0
.
它将验证年份从19或20开始,该月份不大于12且不等于0且该日期不大于31且不等于0。
在线示例
Using your initial example, you could test it like this:
使用您的初始示例,您可以像这样测试它:
$date_regex = '/^(19|20)\d\d[\-\/.](0[1-9]|1[012])[\-\/.](0[1-9]|[12][0-9]|3[01])$/';
$hiredate = '2013-14-04';
if (!preg_match($date_regex, $hiredate)) {
echo '<br>Your hire date entry does not match the YYYY-MM-DD required format.<br>';
} else {
echo '<br>Your date is set correctly<br>';
}
在线示例
#2
13
Do not use regex for this, you can get the same result by using DateTime::createFromFormat
不要使用正则表达式,使用DateTime :: createFromFormat可以得到相同的结果
// specify your date's original format, in this example m/d/Y (e.g. 08/31/2013)
$format = "m/d/Y";
$hireDate = DateTime::createFromFormat($format, $_POST['hiredate']);
if(!$hireDate) {
// createFromFormat returns false if the format is invalid;
} else {
//change it to any format you want with format() (e.g. 2013-08-31)
echo $hireDate->format("Y-m-d");
}
you can read more here:
你可以在这里阅读更多:
http://php.net/manual/en/datetime.createfromformat.php
http://php.net/manual/en/datetime.createfromformat.php
However, it seems like the issue is totally unrelated to PHP.
但是,似乎这个问题与PHP完全无关。
PHP runs on the back end, and it seems like you have a front end problem.
PHP运行在后端,看起来你有一个前端问题。
I also doubt the problem is the input type you use. If one browser doesn't support the input type you specified, then it defaults to text. See it here:
我也怀疑问题是你使用的输入类型。如果一个浏览器不支持您指定的输入类型,则默认为文本。在这里看到:
http://jsfiddle.net/FKGCA/
My browser doesn't know what the <input type="whatever" />
is, so it defaults the input type to "text". If I wrap those 4 inputs in a <form action="myForm.php" method="POST"></form>
tag, the browser sends the inputs to the server because the server doesn't care/know if the inputs were hidden, radio buttons, selects, texts, or password. The servers only receives raw-data.
我的浏览器不知道是什么,因此它将输入类型默认为“text”。如果我将这4个输入包装在
More than likely, your issue is with your Javascript, and not with your PHP. Try to see if the browser that doesn't display your widget tells you that there's an error of some kind in your page.
更有可能的是,您的问题在于您的Javascript,而不是您的PHP。尝试查看未显示小部件的浏览器是否告诉您页面中存在某种错误。
Safari and Firefox have development/debugging tools, not so sure about IE.
Safari和Firefox都有开发/调试工具,对IE不太确定。
#3
0
Check and validate YYYY-MM-DD
date in one line statement
在一行声明中检查并验证YYYY-MM-DD日期
function isValidDate($date) {
return preg_match("/^(\d{4})-(\d{1,2})-(\d{1,2})$/", $date, $m)
? checkdate(intval($m[2]), intval($m[3]), intval($m[1]))
: false;
}
See the details in my answer here.
请参阅我的答案中的详细信息。
Don't use blindly DateTime::createFromFormat
to validate dates. Let's take non-existent date 2018-02-30
and see:
不要盲目使用DateTime :: createFromFormat来验证日期。让我们看2018-02-30不存在的日期,看看:
$d = DateTime::createFromFormat("Y-m-d", "2018-02-30");
var_dump((bool) $d); // bool(true)
Yes, it returns true
, not false
as you may expected. More interesting:
是的,它会返回true,而不是您所预期的错误。更有意思的:
$d = DateTime::createFromFormat("Y-m-d", "2018-99-99");
var_dump((bool) $d); // bool(true)
Also true
... So, it validates just the number of digits. One more try:
同样如此......因此,它只验证数字位数。再试一次:
$d = DateTime::createFromFormat("Y-m-d", "ABCD-99-99");
var_dump($d); // bool(false)
At last false
.
最后是假的。
What is going on here we can see from this snippet:
我们可以从这个片段看到这里发生了什么:
$d = DateTime::createFromFormat("Y-m-d", "2018-02-30");
var_dump($d);
// var_dump OUTPUT
object(DateTime)#1 (3) {
["date"]=>
string(26) "2018-03-02 16:41:34.000000"
["timezone_type"]=>
int(3)
["timezone"]=>
string(3) "UTC"
}
As you can see when we pass non-existent 2018-02-30
, the DateTime
object contains 2018-03-02
. I assume that it's because February 2018 has 28 days, i.e. the maximum date is 2018-02-28
, and when we pass the day 30
, createFromFormat just adds 30 days to the 2018-02-01
and create new date without any preceding date validation.
正如您所看到的那样,当我们传递不存在的2018-02-30时,DateTime对象包含2018-03-02。我认为这是因为2018年2月有28天,即最长日期是2018-02-28,当我们通过第30天时,createFromFormat只增加30天到2018-02-01并创建新日期而没有任何先前日期验证。
#1
10
Your regex didn't work because you had unescaped /
delimiter.
你的正则表达式没有用,因为你有未转义/分隔符。
The regex that would validate date in format YYYY-MM-DD
as follows:
将以YYYY-MM-DD格式验证日期的正则表达式如下:
^(19|20)\d\d[\-\/.](0[1-9]|1[012])[\-\/.](0[1-9]|[12][0-9]|3[01])$
It will validate that the year starts with 19
or 20
, that the month is not greater than 12
and doesn't equal 0
and that the day is not greater than 31
and doesn't equal 0
.
它将验证年份从19或20开始,该月份不大于12且不等于0且该日期不大于31且不等于0。
在线示例
Using your initial example, you could test it like this:
使用您的初始示例,您可以像这样测试它:
$date_regex = '/^(19|20)\d\d[\-\/.](0[1-9]|1[012])[\-\/.](0[1-9]|[12][0-9]|3[01])$/';
$hiredate = '2013-14-04';
if (!preg_match($date_regex, $hiredate)) {
echo '<br>Your hire date entry does not match the YYYY-MM-DD required format.<br>';
} else {
echo '<br>Your date is set correctly<br>';
}
在线示例
#2
13
Do not use regex for this, you can get the same result by using DateTime::createFromFormat
不要使用正则表达式,使用DateTime :: createFromFormat可以得到相同的结果
// specify your date's original format, in this example m/d/Y (e.g. 08/31/2013)
$format = "m/d/Y";
$hireDate = DateTime::createFromFormat($format, $_POST['hiredate']);
if(!$hireDate) {
// createFromFormat returns false if the format is invalid;
} else {
//change it to any format you want with format() (e.g. 2013-08-31)
echo $hireDate->format("Y-m-d");
}
you can read more here:
你可以在这里阅读更多:
http://php.net/manual/en/datetime.createfromformat.php
http://php.net/manual/en/datetime.createfromformat.php
However, it seems like the issue is totally unrelated to PHP.
但是,似乎这个问题与PHP完全无关。
PHP runs on the back end, and it seems like you have a front end problem.
PHP运行在后端,看起来你有一个前端问题。
I also doubt the problem is the input type you use. If one browser doesn't support the input type you specified, then it defaults to text. See it here:
我也怀疑问题是你使用的输入类型。如果一个浏览器不支持您指定的输入类型,则默认为文本。在这里看到:
http://jsfiddle.net/FKGCA/
My browser doesn't know what the <input type="whatever" />
is, so it defaults the input type to "text". If I wrap those 4 inputs in a <form action="myForm.php" method="POST"></form>
tag, the browser sends the inputs to the server because the server doesn't care/know if the inputs were hidden, radio buttons, selects, texts, or password. The servers only receives raw-data.
我的浏览器不知道是什么,因此它将输入类型默认为“text”。如果我将这4个输入包装在
More than likely, your issue is with your Javascript, and not with your PHP. Try to see if the browser that doesn't display your widget tells you that there's an error of some kind in your page.
更有可能的是,您的问题在于您的Javascript,而不是您的PHP。尝试查看未显示小部件的浏览器是否告诉您页面中存在某种错误。
Safari and Firefox have development/debugging tools, not so sure about IE.
Safari和Firefox都有开发/调试工具,对IE不太确定。
#3
0
Check and validate YYYY-MM-DD
date in one line statement
在一行声明中检查并验证YYYY-MM-DD日期
function isValidDate($date) {
return preg_match("/^(\d{4})-(\d{1,2})-(\d{1,2})$/", $date, $m)
? checkdate(intval($m[2]), intval($m[3]), intval($m[1]))
: false;
}
See the details in my answer here.
请参阅我的答案中的详细信息。
Don't use blindly DateTime::createFromFormat
to validate dates. Let's take non-existent date 2018-02-30
and see:
不要盲目使用DateTime :: createFromFormat来验证日期。让我们看2018-02-30不存在的日期,看看:
$d = DateTime::createFromFormat("Y-m-d", "2018-02-30");
var_dump((bool) $d); // bool(true)
Yes, it returns true
, not false
as you may expected. More interesting:
是的,它会返回true,而不是您所预期的错误。更有意思的:
$d = DateTime::createFromFormat("Y-m-d", "2018-99-99");
var_dump((bool) $d); // bool(true)
Also true
... So, it validates just the number of digits. One more try:
同样如此......因此,它只验证数字位数。再试一次:
$d = DateTime::createFromFormat("Y-m-d", "ABCD-99-99");
var_dump($d); // bool(false)
At last false
.
最后是假的。
What is going on here we can see from this snippet:
我们可以从这个片段看到这里发生了什么:
$d = DateTime::createFromFormat("Y-m-d", "2018-02-30");
var_dump($d);
// var_dump OUTPUT
object(DateTime)#1 (3) {
["date"]=>
string(26) "2018-03-02 16:41:34.000000"
["timezone_type"]=>
int(3)
["timezone"]=>
string(3) "UTC"
}
As you can see when we pass non-existent 2018-02-30
, the DateTime
object contains 2018-03-02
. I assume that it's because February 2018 has 28 days, i.e. the maximum date is 2018-02-28
, and when we pass the day 30
, createFromFormat just adds 30 days to the 2018-02-01
and create new date without any preceding date validation.
正如您所看到的那样,当我们传递不存在的2018-02-30时,DateTime对象包含2018-03-02。我认为这是因为2018年2月有28天,即最长日期是2018-02-28,当我们通过第30天时,createFromFormat只增加30天到2018-02-01并创建新日期而没有任何先前日期验证。