PHP Regex để kiểm tra ngày ở định dạng YYYY-MM-DD


97

Tôi đang cố gắng kiểm tra xem các ngày do người dùng cuối nhập có nằm trong YYYY-MM-DD hay không. Regex chưa bao giờ là điểm mạnh của tôi, tôi liên tục nhận được giá trị trả về sai cho preg_match () mà tôi đã thiết lập.

Vì vậy, tôi giả định rằng tôi đã tạo ra một mớ hỗn độn của regex, được trình bày chi tiết bên dưới.

$date="2012-09-12";

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

Có suy nghĩ gì không?


6
Regex không đủ để xác thực một ngày. Sau regex, bạn cũng nên sử dụng một trong hai: date("Y-m-d", strtotime("2012-09-12"))=="2012-09-12";hoặc PHP checkdate ( int $month , int $day , int $year ).
Tiberiu-Ionuț Stan

Tôi không cố gắng xác thực nó tại thời điểm này, tôi chỉ muốn đảm bảo nó ở định dạng YYYY-MM-DD.
cosmicsafari

2
Đối với giá trị do người dùng nhập, còn "thời điểm" nào tốt hơn để xác thực không phải là ngay sau regex, khi gửi biểu mẫu (để bạn có thể hiển thị lỗi)?
Tiberiu-Ionuț Stan

Điểm hợp lý, có thể tiết kiệm một hickup sau này.
cosmicsafari

Câu trả lời:


196

Thử cái này.

$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;
}

18
return (bool)preg_match("/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/",$date);
Tiberiu-Ionuț Stan

5
Tại sao điều này được đánh dấu là câu trả lời đúng? Điều này trả về true cho một số ngày không hợp lệ như 2016-02-30 và 2016-09-31
Graham.

7
Câu hỏi này là về cách kiểm tra định dạng ngày (YYYY-MM-DD) và câu trả lời được đánh dấu là được chấp nhận không phải lúc nào cũng là câu trả lời tốt nhất, nó chỉ có nghĩa là nó phù hợp với người đã hỏi, hãy đọc chuyến tham quan tuyệt vời này: stackoverflow. com / tour .
stramin

@Graham bài cũ tôi biết nhưng đồng ý với Stramin - câu hỏi này hỏi về xác định dạng - xác nhận ngày không thực tế
treyBake

98

Có lẽ tốt hơn nên sử dụng cơ chế khác cho việc này.

Giải pháp hiện đại, với DateTime:

$dt = DateTime::createFromFormat("Y-m-d", $date);
return $dt !== false && !array_sum($dt::getLastErrors());

Điều này cũng xác thực đầu vào: $dt !== falseđảm bảo rằng ngày có thể được phân tích cú pháp với định dạng được chỉ định và array_sumthủ thuật là một cách ngắn gọn để đảm bảo rằng PHP không thực hiện "dịch chuyển tháng" (ví dụ: xem ngày 32 tháng 1 là ngày 1 tháng 2). Xem DateTime::getLastErrors()để biết thêm thông tin.

Giải pháp cũ với explodecheckdate:

list($y, $m, $d) = array_pad(explode('-', $date, 3), 3, 0);
return ctype_digit("$y$m$d") && checkdate($m, $d, $y);

Điều này xác nhận rằng đầu vào cũng là một ngày hợp lệ. Tất nhiên, bạn có thể làm điều đó với regex, nhưng nó sẽ phức tạp hơn - và ngày 29 tháng 2 không thể được xác nhận bằng regex.

Hạn chế của phương pháp này là bạn phải rất cẩn thận để từ chối tất cả các đầu vào "xấu" có thể xảy ra trong khi không phát ra thông báo trong bất kỳ trường hợp nào. Đây là cách thực hiện:

  • explodeđược giới hạn để trả về 3 mã thông báo (để nếu đầu vào là "1-2-3-4", $dsẽ trở thành "3-4")
  • ctype_digit được sử dụng để đảm bảo rằng đầu vào không chứa bất kỳ ký tự không phải số nào (ngoài dấu gạch ngang)
  • array_padđược sử dụng (với giá trị mặc định sẽ gây ra checkdatelỗi) để đảm bảo rằng có đủ phần tử được trả về để nếu đầu vào là "1-2" list()sẽ không phát ra thông báo

+1, luôn được sử dụng DateTimevà chưa bao giờ nghe về checkdate... xấu hổ về tôi.
k102

@ k102: DateTimecũng có thể làm được điều này. Tôi vừa hoàn thành câu trả lời, hãy xem lại nếu bạn muốn.
Jon

Nhìn vào hướng dẫn sử dụng PHP, có vẻ như giải pháp đầu tiên sẽ xác nhận các ngày chưa hoàn thành (điền vào các giá trị còn thiếu so với ngày hiện tại).
user2428118

Một vấn đề khác với giải pháp # 1: "các giá trị không tồn tại cuộn qua", ví dụ: 2001-02-31 trở thành 2001-03-03. (Mặc dù OP chưa hỏi rõ ràng rằng điều này là không thể.)
user2428118

1
@ user2428118: Bạn đã thử giải pháp số 1 chính xác như đã cho hay chỉ là dòng đầu tiên? Bạn có nhấp vào liên kết tôi cung cấp cho tài liệu getLastErrorskhông?
Jon

42

yyyy-mm-dd: /^((((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

yyyy / mm / dd: /^((((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

mm-dd-yyyy: /^(((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

mm / dd / yyyy: /^(((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

dd / mm / yyyy: /^(((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

dd-mm-yyyy: /^(((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


Tất cả những điều trên đều hoạt động cho các ngày từ năm 1900 đến năm 9999, đây là những ngày cần thiết nhất và ngắn hơn 74 ký tự so với nỗ lực của tôi (lại là định dạng yyyy-mm-dd). nếu bạn muốn các ngày trước năm 1900, thì một chỉnh sửa nhỏ đối với câu trả lời Shyju sẽ cho phép từ năm 1000 và ngắn hơn 23 ký tự: ^ ((([1-9] \ d {3}) \ - (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)) | (([1-9] \ d {3}) \ - 02 \ - (0 [1-9] | 1 \ d | 2 [0-8])) | (([1-9] \ d (0 [48] | [2468] [048] | [13579] [26]) | ( (16 | [2468] [048] | [3579] [26]) 00)) \ - 02 \ -29)) $
Graham

36

Tiêu chí:

Năm nào chia hết cho 4 là năm nhuận, trừ khi chia hết cho 100 trừ khi chia hết cho 400. Vì vậy:

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

Tháng 2 có 29 ngày trong năm nhuận và 28 ngày không phải năm nhuận

30 ngày trong tháng 4, 6, 9 và 11

31 ngày trong tháng 1, 3, 5, 7, 8, 10 và 12

Kiểm tra:

Tất cả các ngày sau đây đều phải vượt qua xác thực:

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

Tất cả các ngày sau đây sẽ không xác thực được:

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

Phạm vi:

Chúng tôi sẽ kiểm tra các ngày từ ngày 1 tháng 1 năm 1000 đến ngày 31 tháng 12 năm 2999. Về mặt kỹ thuật, lịch Gregorian hiện đang được sử dụng chỉ được sử dụng vào năm 1753 cho Đế quốc Anh và vào những năm khác nhau trong những năm 1600 cho các quốc gia ở Châu Âu, nhưng tôi sẽ không lo lắng về điều đó.

Regex để kiểm tra một năm nhuận:

Các năm chia hết cho 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

Các năm chia hết cho 4:

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

Các năm chia hết cho 100:

[12]\d00

Không chia hết cho 100:

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

Các năm chia hết cho 100 nhưng không chia hết cho 400:

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

Chia hết cho 4 nhưng không chia hết cho 100:

[12]\d([2468][048]|[13579][26]|0[48])

Những năm nhuận:

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])

Không chia hết cho 4:

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

Không phải là một năm nhuận:

Not divisible by 4 OR is divisible by 100 but not by 400
([12]\d([02468][1235679]|[13579][01345789]))|(((1[1345789])|(2[1235679]))00)

Tháng và ngày hợp lệ không bao gồm tháng 2 (MM-DD):

((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))

Tháng 2 với 28 ngày:

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

Tháng 2 với 29 ngày:

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

Ngày hợp lệ:

(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]))))

Vì vậy, bạn có nó là regex cho các ngày từ ngày 1 tháng 1 năm 1000 đến ngày 31 tháng 12 năm 2999 ở định dạng YYYY-MM-DD.

Tôi nghi ngờ nó có thể được rút ngắn một chút, nhưng tôi sẽ để điều đó cho người khác.

Điều đó sẽ phù hợp với tất cả các ngày hợp lệ. Nếu bạn muốn nó chỉ hợp lệ khi nó chỉ chứa một ngày và không có gì khác, thì hãy bọc nó lại ^( )$như sau:

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

Nếu bạn muốn nó cho một mục ngày tùy chọn (nghĩa là nó có thể để trống hoặc một ngày hợp lệ) thì hãy thêm ^$|vào đầu, như sau:

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

7
Đó là một biểu hiện anh hùng, và được giải thích rất tốt.
môi trường xung quanh

Bạn có bằng chứng chắc chắn rằng nó sẽ vượt qua mọi trường hợp hợp lệ và thất bại trong mọi trường hợp không hợp lệ không?
Md Ashraful Islam

@Md Ashraful Islam No
Graham

@Graham Altough không sao, chúng tôi đang sử dụng nó trong trang web của mình. Tôi hy vọng sẽ không có vấn đề gì xảy ra.
Md Ashraful Islam

@Md Ashraful Islam - Chúng tôi cũng sử dụng nó và không gặp vấn đề gì với nó cho đến nay
Graham

18

Bạn có thể làm theo cách này:

if (preg_match("/\d{4}\-\d{2}-\d{2}/", $date)) {
    echo 'true';
} else {
    echo 'false';
}

nhưng tốt hơn bạn nên sử dụng cái này:

$date = DateTime::createFromFormat('Y-m-d', $date);
if ($date) {
    echo $date -> format('Y-m-d');
}

trong trường hợp này, bạn sẽ nhận được một đối tượng dễ sử dụng hơn là chỉ chuỗi.


1
Kỹ thuật dateTime được sử dụng ở đây sẽ trả về true cho một ngày như 2016-05-44 không phải là ngày thực tế
nonybrighto

Đây không phải là một ví dụ điển hình, đặc biệt nếu bạn muốn hẹn hò (Ymd). Ví dụ: 0175-44-19927sẽ qua.
Attila Naghi

7

Tôi biết rằng đây là một câu hỏi cũ. Nhưng tôi nghĩ rằng tôi có một giải pháp tốt.

$date = "2016-02-21";
$format = "Y-m-d";

if(date($format, strtotime($date)) == date($date)) {
    echo "true";
} else {
    echo "false";
}

Bạn có thể thử nó. Nếu bạn thay đổi ngày thành 21.02.2016 thì tiếng vọng là sai. Và nếu bạn thay đổi định dạng sau đó thành dmY thì tiếng vọng là true.

Với mã dễ dàng này, bạn sẽ có thể kiểm tra định dạng ngày được sử dụng mà không cần kiểm tra bằng regex.

Có thể có một người sẽ kiểm tra nó trên mọi trường hợp. Nhưng tôi nghĩ ý tưởng của tôi nói chung là hợp lệ. Đối với tôi nó có vẻ hợp lý.


Tôi không nghĩ bạn cần ngày () khoảng $ date trên dòng if. if (date ($ format, strtotime ($ date)) == $ date) - phải đủ
iateadonut Ngày

7

Bạn có thể sử dụng preg_match với hàm checkdate php

$date  = "2012-10-05";
$split = array();
if (preg_match ("/^([0-9]{4})-([0-9]{2})-([0-9]{2})$/", $date, $split))
{
    return checkdate($split[2], $split[3], $split[1]);
}

return false;

return preg_match ("/ ^ ([0-9] {4}) - ([0-9] {2}) - ([0-9] {2}) $ /", $ date, $ split)) && checkdate ($ split [2], $ split [3], $ split [1]);
Tiberiu-Ionuț Stan

5

preg_match cần một / hoặc một ký tự khác làm dấu phân cách.

preg_match("/^[0-9]{4}-[0-1][0-9]-[0-3][0-9]$/",$date)

bạn cũng nên kiểm tra tính hợp lệ của ngày đó để không kết thúc với một cái gì đó như 9999-19-38

bool checkdate ( int $month , int $day , int $year )

3

Bạn cũng có thể làm như thế này:

if (DateTime::createFromFormat('Y-m-d', $date)->format('Y-m-d') === $date) {

    // date is correctly formatted and valid, execute some code

}

Điều này sẽ không chỉ kiểm tra định dạng mà còn cả tính hợp lệ của chính ngày tháng, vì DateTimesẽ chỉ tạo ra các ngày hợp lệ và điều này cần phải khớp với đầu vào.


3

bạn có thể dùng

function validateDate($date, $format = 'Y-m-d H:i:s')
{
    $d = DateTime::createFromFormat($format, $date);
    return $d && $d->format($format) == $date;
}

$date="2012-09-12";    
echo validateDate($date, 'Y-m-d'); // true or false

2

Kiểm tra và xác nhận YYYY-MM-DDngày trong câu lệnh một dòng

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;
}

Đầu ra sẽ là:

var_dump(isValidDate("2018-01-01")); // bool(true)
var_dump(isValidDate("2018-1-1"));   // bool(true)
var_dump(isValidDate("2018-02-28")); // bool(true)
var_dump(isValidDate("2018-02-30")); // bool(false)

Ngày và tháng không có số 0 đứng đầu được cho phép. Nếu bạn không muốn cho phép điều này, regexp phải là:

"/^(\d{4})-(\d{2})-(\d{2})$/"

1

Nếu bạn muốn khớp với loại ngày đó, hãy sử dụng:

preg_match("~^\d{4}-\d{2}-\d{2}$~", $date)

1

Điều này sẽ cho bạn biết liệu định dạng có hợp lệ và ngày nhập liệu có hợp lệ hay không.

    $datein = '2012-11-0';

    if(preg_match('/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/', $datein)){
        echo 'good';
    }else{
        echo 'no good';
    }

1

Nếu nó có ích gì, đây là định dạng regex cho jnY (năm phải lớn hơn 2018):

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
}

1

Định dạng 1: $ format1 = "2012-12-31";

Định dạng 2: $ format2 = "31-12-2012";

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

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

1

Có thể hữu ích cho ai đó:

$patterns = array(
            'Y'           =>'/^[0-9]{4}$/',
            'Y-m'         =>'/^[0-9]{4}(-|\/)([1-9]|0[1-9]|1[0-2])$/',
            'Y-m-d'       =>'/^[0-9]{4}(-|\/)([1-9]|0[1-9]|1[0-2])(-|\/)([1-9]|0[1-9]|[1-2][0-9]|3[0-1])$/',
            'Y-m-d H'     =>'/^[0-9]{4}(-|\/)([1-9]|0[1-9]|1[0-2])(-|\/)([1-9]|0[1-9]|[1-2][0-9]|3[0-1])\s(0|[0-1][0-9]|2[0-4])$/',
            'Y-m-d H:i'   =>'/^[0-9]{4}(-|\/)([1-9]|0[1-9]|1[0-2])(-|\/)([1-9]|0[1-9]|[1-2][0-9]|3[0-1])\s(0|[0-1][0-9]|2[0-4]):?(0|[0-5][0-9]|60)$/',
            'Y-m-d H:i:s' =>'/^[0-9]{4}(-|\/)([1-9]|0[1-9]|1[0-2])(-|\/)([1-9]|0[1-9]|[1-2][0-9]|3[0-1])\s(0|[0-1][0-9]|2[0-4]):?((0|[0-5][0-9]):?(0|[0-5][0-9])|6000|60:00)$/',
        );
echo preg_match($patterns['Y'], '1996'); // true
echo preg_match($patterns['Y'], '19966'); // false
echo preg_match($patterns['Y'], '199z'); // false
echo preg_match($patterns['Y-m'], '1996-0'); // false
echo preg_match($patterns['Y-m'], '1996-09'); // true
echo preg_match($patterns['Y-m'], '1996-1'); // true
echo preg_match($patterns['Y-m'], '1996/1'); // true
echo preg_match($patterns['Y-m'], '1996/12'); // true
echo preg_match($patterns['Y-m'], '1996/13'); // false
echo preg_match($patterns['Y-m-d'], '1996-11-1'); // true
echo preg_match($patterns['Y-m-d'], '1996-11-0'); // false
echo preg_match($patterns['Y-m-d'], '1996-11-32'); // false
echo preg_match($patterns['Y-m-d H'], '1996-11-31 0'); // true
echo preg_match($patterns['Y-m-d H'], '1996-11-31 00'); // true
echo preg_match($patterns['Y-m-d H'], '1996-11-31 24'); // true
echo preg_match($patterns['Y-m-d H'], '1996-11-31 25'); // false
echo preg_match($patterns['Y-m-d H:i'], '1996-11-31 2400'); // true
echo preg_match($patterns['Y-m-d H:i'], '1996-11-31 24:00'); // true
echo preg_match($patterns['Y-m-d H:i'], '1996-11-31 24:59'); // true
echo preg_match($patterns['Y-m-d H:i'], '1996-11-31 24:60'); // true
echo preg_match($patterns['Y-m-d H:i'], '1996-11-31 24:61'); // false
echo preg_match($patterns['Y-m-d H:i'], '1996-11-31 24:61'); // false
echo preg_match($patterns['Y-m-d H:i:s'], '1996-11-31 24:6000'); // true
echo preg_match($patterns['Y-m-d H:i:s'], '1996-11-31 24:60:00'); // true
echo preg_match($patterns['Y-m-d H:i:s'], '1996-11-31 24:59:59'); // true
echo preg_match($patterns['Y-m-d H:i:s'], '1996-11-31 24:59:60'); // false
echo preg_match($patterns['Y-m-d H:i:s'], '1996-11-31 24:60:01'); // false

'1996-11-31 24:00'); // true, có thật không? Hơn nữa, đôi khi có 61 giây trong một phút, hãy xem: en.wikipedia.org/wiki/Leap_second
Toto

1

Chức năng xác thực định dạng ngày chung:

function validateDate($date, $format = 'Y-m-d') {
  $d = DateTime::createFromFormat($format, $date);
  return $d && $d->format($format) == $date;
}

Ví dụ về thực thi:

var_dump(validateDate('2021-02-28')); // true
var_dump(validateDate('2021-02-29')); // false

Vui lòng đặt câu trả lời của bạn luôn trong ngữ cảnh thay vì chỉ dán mã. Xem tại đây để biết thêm chi tiết. Xin vui lòng chỉnh sửa câu trả lời của bạn để chứa tất cả các phần của mã trong khối markdown
gehbiszumeis

0

Tất cả phụ thuộc vào mức độ nghiêm ngặt mà bạn muốn chức năng này. Ví dụ: nếu bạn không muốn cho phép các tháng trên 12 và các ngày trên 31 (không phụ thuộc vào tháng, điều đó sẽ yêu cầu viết logic ngày), nó có thể trở nên khá phức tạp:

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');

Cá nhân tôi chỉ muốn: /^([0-9]{4}\-([0-9]{2}\-[0-9]{2})$/


4
Regex này phức tạp một cách không cần thiết. 0[1-9]|1[0-2]các trận đấu tháng 01-12 và các 0[1-9]|[12][0-9]|3[01]trận đấu ngày 01-31.
estrar

Xin lỗi khi tôi nôn
AlxVallejo

0

Để làm việc với ngày tháng trong php, bạn nên tuân theo tiêu chuẩn php để regex đã cho sẽ đảm bảo rằng bạn có ngày hợp lệ có thể hoạt động với PHP.

    preg_match("/^([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/",$date)

Rgex của bạn là sai, nó sẽ không khớp 1980-01-01nhưng sẽ khớp2100-02-29
Toto

0

Phương pháp này có thể hữu ích để xác thực ngày tháng trong PHP. Phương pháp hiện tại dành cho định dạng mm / dd / yyyy. Bạn phải cập nhật chuỗi thông số trong ngày kiểm tra theo định dạng của bạn và dấu phân cách trong thời gian bùng nổ .

    function isValidDate($dt)
    {
        $dtArr = explode('/', $dt);
        if (!empty($dtArr[0]) && !empty($dtArr[1]) && !empty($dtArr[2])) {
            return checkdate((int) $dtArr[0], (int) $dtArr[1], (int) $dtArr[2]);
        } else {
            return false;
        }
    }

0

[Nếu bạn sử dụng Symfony 4.1.2, hãy thử cái này] [1]

  $validDate = explode("-",$request->get('date'));
        if (checkdate(filter_var($validDate[1],FILTER_SANITIZE_NUMBER_INT),filter_var($validDate[0],FILTER_SANITIZE_NUMBER_INT),filter_var($validDate[2],FILTER_SANITIZE_NUMBER_INT))){
            $date = date_create(filter_var($request->get('date'),FILTER_SANITIZE_SPECIAL_CHARS));
        }else{
            return $this->redirectToRoute('YOUR_ROUTE');
        }

0

Từ Laravel 5.7 và định dạng ngày tức là: 31/12/2019

function checkDateFormat(string $date): bool
{
    return preg_match("/^(0[1-9]|1[0-2])\/(0[1-9]|[1-2][0-9]|3[0-1])\/[0-9]{4}$/", $date);
}

0

Tôi đã tìm kiếm "cách xác thực ngày" và tìm thấy giải pháp này, Phương pháp cũ nhưng tôi sẽ chia sẻ bên dưới có thể được sử dụng để xác thực ngày trong php,

checkdate('01', '31', '2019')
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.