2013-11-04 17 views
7

Tôi đang cố gắng thực hiện bộ kiểm tra ngày tháng regex. Vấn đề tôi gặp phải là tôi đang sử dụng trường nhập với loại "date", hoạt động như một nét duyên dáng trong Chrome; nó sẽ mở ra một lịch giống như trong Chrome, nhưng trong phần còn lại nó không có gì, vì vậy tôi quyết định đi cho một đầu vào thủ công của ngày cho phần còn lại.Regex để xác thực ngày bằng PHP sử dụng định dạng là YYYY-MM-DD

Đây là thông điệp ném lỗi của tôi (tôi đang tìm kiếm định dạng 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.'; 
} 

Tôi biết có rất nhiều ví dụ về điều này, nhưng tôi đã cố gắng như 20 đã và tôi không thể giải quyết nó. Có lẽ tôi đang thiếu một cái gì đó.

Dưới đây là lĩnh vực đầu vào, nếu phần nào có liên quan:

<input type="date" name="hiredate" /> 
+1

Tại sao không phát nổ bằng - và sử dụng checkdate() thay thế? –

+0

Có quy trình chuẩn không? Tôi tìm thấy nó trong một bài viết khác nhưng không làm việc cho tôi. FYI, tôi muốn để chúng chèn vào như YYYY/MM/DD hoặc YYYY.MM.DD hoặc YYYY-MM-DD. Để không kiềm chế chúng quá nhiều. – Cataneo

+3

Sẽ dễ dàng hơn khi cung cấp 3 hộp '' riêng biệt với một chiều dài thích hợp và chỉ xác thực chữ số được hợp nhất thành định dạng thích hợp trên chương trình phụ trợ không? Bạn có thể thêm người nghe vào mỗi ô nhập liệu để chuyển sang hộp thoại tiếp theo nếu một người 'bấm phím' 2 chữ số. Người dùng không cung cấp cho một con chuột đằng sau về định dạng bạn cần và bạn sẽ chỉ làm họ thất vọng nhất nếu nó không phải là định dạng gốc riêng của họ – MonkeyZeus

Trả lời

10

Regex của bạn không hoạt động vì bạn có unescaped/ dấu phân cách.

Các regex mà sẽ xác nhận ngày ở định dạng YYYY-MM-DD như sau:

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

Nó sẽ xác nhận rằng năm nay bắt đầu với 19 hoặc 20, trong tháng đó không phải là lớn hơn 12 và không bằng 0 và ngày đó không lớn hơn 31 và không bằng 0.

Example Online

Sử dụng ví dụ ban đầu của bạn, bạn có thể kiểm tra nó như thế này:

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

Example Online

+1

Đúng vậy, điều này làm việc ổn. Tôi đã sử dụng rất nhiều biến thể của regex tôi phải thay đổi nó rất tệ. Tuyệt vời mắt bạn có Ilia Rostovtsev. – Cataneo

13

Không sử dụng regex cho điều này, bạn có thể nhận được kết quả tương tự bằng cách sử dụng 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"); 
} 

bạn có thể đọc thêm ở đây:

http://php.net/manual/en/datetime.createfromformat.php

Ho wever, có vẻ như vấn đề là hoàn toàn không liên quan đến PHP.

PHP chạy ở mặt sau và có vẻ như bạn gặp sự cố giao diện người dùng.

Tôi cũng nghi ngờ vấn đề là loại đầu vào bạn sử dụng. Nếu một trình duyệt không hỗ trợ kiểu nhập bạn đã chỉ định, thì trình duyệt sẽ mặc định là văn bản. Nhìn thấy nó ở đây:

http://jsfiddle.net/FKGCA/

Trình duyệt của tôi không biết <input type="whatever" /> là gì, vì vậy nó mặc định các loại đầu vào "văn bản". Nếu tôi bọc 4 đầu vào đó vào một thẻ <form action="myForm.php" method="POST"></form>, trình duyệt sẽ gửi các đầu vào đến máy chủ vì máy chủ không quan tâm/biết nếu các đầu vào bị ẩn, nút radio, lựa chọn, văn bản hoặc mật khẩu. Các máy chủ chỉ nhận dữ liệu thô.

Nhiều khả năng vấn đề của bạn là với Javascript, chứ không phải với PHP của bạn. Hãy thử xem liệu trình duyệt không hiển thị tiện ích của bạn có cho bạn biết rằng có một lỗi nào đó trong trang của bạn.

Safari và Firefox có công cụ phát triển/gỡ lỗi, không chắc chắn về IE.

+0

Đó là chính xác những gì tôi đã nói. "Tiện ích" hoạt động trong Chrome và được chuyển đổi thành kiểu nhập văn bản trong các loại khác. Đó là chính xác những gì tôi đang cố gắng để xác nhận. Tôi có định dạng ngày và chia nhỏ trường thành ba và sẽ đi từ đó. – Cataneo

+1

gotcha, cho các trường hợp như thế này là khi jQuery có ích. Nếu không, bạn sẽ cần kiểm tra hỗ trợ: http://diveintohtml5.info/detect.html#input-types và nếu nó không được hỗ trợ. Bạn sẽ phải sử dụng các lựa chọn thay thế dựa trên javascript (như jQuery) – ILikeTacos

0

Kiểm tra và xác nhận YYYY-MM-DD ngày trong một tuyên bố 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; 
} 

Xem các chi tiết trong câu trả lời của tôi here.

Không sử dụng một cách mù quáng DateTime::createFromFormat để xác thực ngày. Chúng ta hãy cùng ngày không tồn tại 2018-02-30 và xem:

$d = DateTime::createFromFormat("Y-m-d", "2018-02-30"); 
var_dump((bool) $d); // bool(true) 

Có, nó sẽ trả true, không false như bạn có thể mong đợi. Thú vị hơn:

$d = DateTime::createFromFormat("Y-m-d", "2018-99-99"); 
var_dump((bool) $d); // bool(true) 

Cũng true ... Vì vậy, nó chỉ xác nhận số chữ số. Một lần nữa thử:

$d = DateTime::createFromFormat("Y-m-d", "ABCD-99-99"); 
var_dump($d); // bool(false) 

Cuối cùng false.

gì đang xảy ra ở đây chúng ta có thể nhìn thấy từ đoạn này:

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

Như bạn có thể nhìn thấy khi chúng ta vượt qua không tồn tại 2018-02-30, đối tượng DateTime chứa 2018-03-02. Tôi cho rằng đó là vì tháng 2 năm 2018 có 28 ngày, tức là ngày tối đa là 2018-02-28 và khi chúng tôi vượt qua ngày 30, createFromFormat chỉ thêm 30 ngày vào 2018-02-01 và tạo ngày mới mà không có bất kỳ xác thực ngày nào trước đó.

Các vấn đề liên quan