2012-05-21 62 views
39

Tôi đang làm việc trên tập lệnh sẽ nhập một số dữ liệu từ tệp CSV. Khi tôi làm điều này, tôi muốn có thể kiểm tra một biến để xem đó có phải là chuỗi ngày hợp lệ hay không.Kiểm tra xem biến có phải là ngày hợp lệ với PHP

Tôi đã nhìn thấy một số cách để kiểm tra xem dấu vết có phải là ngày hay không, nhưng hầu hết trong số chúng yêu cầu bạn định dạng. Tôi sẽ không biết định dạng mà ngày sẽ trong.

ngay bây giờ tôi đang sử dụng strtotime(), nhưng điều này không dễ dàng

$field ="May"; 
if(strtotime($field)){ 
    echo "This is a date"; 
} 

Trong trường hợp này, "May" là người tên đầu tiên, và không phải là một ngày nào cả.

Có thể bất kỳ ai đề xuất chức năng đáng tin cậy hơn không?

Chỉnh sửa dựa trên câu hỏi của một số bạn.

Để biến được chuyển thành "ngày" trong trường hợp của tôi, nó sẽ cần phải cụ thể cho một ngày/tháng/năm, vì vậy chỉ "tháng" sẽ mơ hồ để đếm.

Trên cơ sở đó và Pauls điểm tốt dưới đây, chúng tôi cũng có thể kiểm tra để xem nếu chuỗi có chứa một số, chẳng hạn như

$field ="May"; 
if(strtotime($field) && 1 === preg_match('~[0-9]~', $field)){ 
    echo "This is a date"; 
}else{ 
    echo "Nope not a date"; 
} 

này dường như để trang trải nhu cầu trước mắt của tôi, nhưng có thể bất kỳ một vị trí bất kỳ vấn đề hoặc đề xuất cải tiến?

+0

Kịch bản của bạn sẽ cho biết liệu 'May' là tên hay ngày tháng? – lonesomeday

+2

Bạn cần cung cấp thông số * một số * loại giá trị bạn chấp nhận. Nếu không thì "May" cũng tốt như bất kỳ giá trị nào khác. – JJJ

+0

Kiểm tra xem người đó có tên cuối cùng là – Joelmob

Trả lời

5

Tôi không nghĩ rằng có một câu trả lời tất cả-trong-một cho vấn đề này. Bạn có thể có chiến lược khác nhau tùy thuộc vào trường hợp sử dụng của bạn.

strtotime() của bạn là giải pháp hoàn hảo, nhưng như bạn nói, bạn có thể kết thúc với dương tính giả. Tại sao? Vì có thể có thể là một từ hoặc một tên. Tuy nhiên, kết quả của strtotime('May') là gì?

echo date(DateTime::ISO8601, strtotime('May')); 
2012-05-21T00:00:00+0200 

Vì vậy, chỉ cho tháng sẽ trả về ngày của năm hiện tại và ngày hiện tại bắt đầu vào nửa đêm với tháng cụ thể. Một giải pháp có thể là kiểm tra xem chuỗi của bạn có ngày hiện tại và/hoặc năm hiện tại được bao gồm hay không, theo cách này, bạn có thể kiểm tra để đảm bảo ngày của bạn là ngày đủ điều kiện và hợp lệ.

echo date(DateTime::ISO8601, strtotime('May Day')); // (strtotime() returns false) 
1970-01-01T01:00:00+0100 

echo date(DateTime::ISO8601, strtotime('May 21')); 
2012-05-21T00:00:00+0200 

Một đơn giản strpos() hoặc thậm chí một regex nên thực hiện thủ thuật.

Tuy nhiên hơi lạ và chỉ nên sử dụng nếu bạn không có cách nào khác để thực hiện.

Tôi tin rằng giải pháp tốt hơn là xác định một bộ định dạng hợp lệ và nội suy kết quả để đảm bảo rằng ngày hợp lệ.

$validDateFormatPatterns = array(
'[0-9]{1,2}-[0-9]{1,2}-[0-9]{4}', // 21-05-2012, obviously this pattern is simple and would accept 05-21-2012, 
'the [0-9]{1,2}(th|st|nd|rd) (January|February|...|May|...|December) [0,9]{4}', // The 21st May 2012 
); 

Bạn nên cố gắng bao quát hầu hết các trường hợp và tôi chắc chắn bạn sẽ có thể tìm thấy regex kiểm tra định dạng ngày hiện tại nhất.

Trong mọi trường hợp, đôi khi bạn có thể cần phải thích ứng với chức năng của bạn vì không có cách nào dễ dàng để làm cho nó chống đạn.

56

Sử dụng date_parse và kiểm tra các giá trị của mảng được trả về

$date = date_parse("May") 

// ["year"] == FALSE 
// ["month"] == 5 
// ["day"] == FALSE 

Bạn cũng có thể vượt qua những thành checkdate.

$date = date_parse($someString); 
if ($date["error_count"] == 0 && checkdate($date["month"], $date["day"], $date["year"])) 
    echo "Valid date"; 
else 
    echo "Invalid date"; 
+0

Tôi nghĩ rằng bạn đã nhận được nó ... Bất kỳ ai có thể nhìn thấy bất kỳ sai sót với điều này? – Alex

+0

Một lỗ hổng nhỏ: 'date_parse' sử dụng các quy tắc phân tích cú pháp' strtotime', [quy tắc được xác định rõ nhưng khó tính] (http://www.php.net/manual/en/datetime.formats.php). Có thể gửi dữ liệu trả về ngày pháp lý nhưng không phải là mục đích. – Charles

+2

@Charles mà không yêu cầu định dạng rõ ràng cho đầu vào, mọi thuật toán phân tích ngày tự động sẽ gặp sự cố – saluce

0

Tôi biết điều này đã được hỏi một thời gian dài trước đây, nhưng nhìn xung quanh cho điều này và cố gắng để tránh regex, tôi đến với điều này:

function checkInputIsDate($date) { 
    return (bool)strpbrk($date,1234567890) && strtotime($date); 
} 

này hoạt động bởi vì nó mất đi những vấn đề gửi ở trên, nơi chỉ một tháng được chuyển vào strtotime bằng cách đảm bảo có các số trong chuỗi với strpbrk cũng như xác minh strtotime kết quả đầu ra một ngày.

Và tìm hiểu về một hàm tôi không biết đã tồn tại.

Hy vọng điều này sẽ giúp ai đó.

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