PHP Regex do sprawdzenia daty jest w formacie RRRR-MM-DD

101

Próbuję sprawdzić, czy daty wprowadzone przez użytkowników końcowych są w formacie RRRR-MM-DD. Regex nigdy nie był moją mocną stroną, ciągle otrzymuję fałszywą wartość zwracaną dla preg_match (), którą skonfigurowałem.

Więc zakładam, że zrobiłem bałagan w wyrażeniu regularnym, szczegółowo poniżej.

$date="2012-09-12";

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

jakieś pomysły?

cosmicsafari
źródło
6
Regex nie wystarczy, aby zweryfikować datę. Po wyrażeniu regularnym powinieneś również użyć jednego z tych dwóch: date("Y-m-d", strtotime("2012-09-12"))=="2012-09-12";lub PHP checkdate ( int $month , int $day , int $year ).
Tiberiu-Ionuț Stan
W tym momencie nie próbuję go zweryfikować, chcę tylko upewnić się, że jest w formacie RRRR-MM-DD.
cosmicsafari
2
Dla wartości wprowadzonej przez użytkownika, jaki jest lepszy „punkt” w czasie do sprawdzenia, inny niż tuż po wyrażeniu regularnym, podczas przesyłania formularza (aby można było wyświetlić błąd)?
Tiberiu-Ionuț Stan
Słuszna uwaga, może później zaoszczędzić trochę uwagi.
cosmicsafari

Odpowiedzi:

202

Spróbuj tego.

$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;
}
Avin Varghese
źródło
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
Dlaczego ta odpowiedź została oznaczona jako prawidłowa? Zwraca to true dla wielu nieprawidłowych dat, takich jak 2016-02-30 i 2016-09-31
Graham
7
To pytanie dotyczy tego, jak sprawdzić format daty (RRRR-MM-DD), a odpowiedź oznaczona jako zaakceptowana nie zawsze jest najlepszą odpowiedzią, to po prostu oznacza, że ​​zadziałała dla osoby, która zapytała, przeczytaj tę piękną wycieczkę: stackoverflow. com / tour .
stramin
@Graham stary post Wiem, ale zgadzam się ze Straminem - to pytanie dotyczy walidacji formatu - a nie walidacji aktualnej daty
treyBake
99

Prawdopodobnie lepiej jest użyć do tego innego mechanizmu.

Nowoczesne rozwiązanie z DateTime:

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

To również sprawdza poprawność danych wejściowych: $dt !== falsezapewnia, że ​​data może być analizowana w określonym formacie, a array_sumsztuczka polega na zwięzłym sposobie upewnienia się, że PHP nie wykonuje „przesunięcia miesiąca” (np. Rozważ, że 32 stycznia to 1 lutego). Zobacz, DateTime::getLastErrors()aby uzyskać więcej informacji.

Klasyczne rozwiązanie z explodei checkdate:

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

To sprawdza, czy dane wejściowe są również prawidłową datą. Oczywiście możesz to zrobić za pomocą wyrażenia regularnego, ale będzie to bardziej kłopotliwe - a 29 lutego nie można w ogóle zweryfikować za pomocą wyrażenia regularnego.

Wadą tego podejścia jest to, że musisz bardzo uważać, aby odrzucić wszystkie możliwe „złe” dane wejściowe, nie wysyłając powiadomienia w żadnych okolicznościach. Oto jak:

  • explodejest ograniczona do zwrotu 3 żetonów (więc jeśli wartość wejściowa to „1-2-3-4”, $dzmieni się na „3-4”)
  • ctype_digit służy do upewnienia się, że dane wejściowe nie zawierają żadnych znaków nienumerycznych (oprócz myślników)
  • array_padjest używany (z wartością domyślną, która spowoduje checkdateniepowodzenie), aby upewnić się, że zostanie zwrócona wystarczająca liczba elementów, aby jeśli wejście to "1-2" list(), nie wyemituje powiadomienia
Jon
źródło
+1, zawsze używane DateTimei nigdy nie słyszałem o checkdate... wstyd mi.
k102
@ k102: DateTimeteż może to zrobić. Właśnie skończyłem opracowywać odpowiedź, spójrz ponownie, jeśli chcesz.
Jon
Patrząc na podręcznik PHP, wygląda na to, że pierwsze rozwiązanie zweryfikuje niekompletne daty (uzupełnienie brakujących wartości z aktualnej daty).
user2428118
Kolejny problem z rozwiązaniem nr 1: „przerzucenie nieistniejących wartości”, np. 2001-02-31 zmienia się na 2001-03-03. (Chociaż OP nie zapytał wyraźnie, że nie jest to możliwe.)
user2428118
1
@ user2428118: Czy wypróbowałeś rozwiązanie nr 1 dokładnie tak, jak podano, czy tylko pierwszą linię? Czy kliknąłeś link, który podałem do dokumentacji getLastErrors?
Jon
43

rrrr-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

rrrr / 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

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

Shyju KP
źródło
Przede wszystkim działa dla dat od 1900 do 9999, co jest potrzebne przez większość czasu i jest o 74 znaki krótsze niż moja próba (dotyczy formatu rrrr-mm-dd). jeśli chcesz mieć daty sprzed 1900 r., to drobne poprawki w odpowiedzi Shyju pozwolą od roku 1000 i są o kolejne 23 znaki krótsze: ^ ((([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

Kryteria:

Każdy rok podzielny przez 4 jest rokiem przestępnym, chyba że dzieli się go przez 100, chyba że jest podzielny przez 400. A więc:

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

Luty ma 29 dni w roku przestępnym i 28 dni, gdy nie jest to rok przestępny

30 dni w kwietniu, czerwcu, wrześniu i listopadzie

31 dni w styczniu, marcu, maju, lipcu, sierpniu, październiku i grudniu

Test:

Następujące daty powinny przejść walidację:

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

Poniższe daty powinny zakończyć się niepowodzeniem:

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

Zasięg:

Będziemy testować daty od 1 stycznia 1000 do 31 grudnia 2999. Z technicznego punktu widzenia, obecnie używany kalendarz gregoriański wszedł do użytku dopiero w 1753 r. Dla Imperium Brytyjskiego i w różnych latach w 1600 r. Dla krajów w Europie, ale nie zamierzam martw się o to.

Regex do przetestowania na rok przestępny:

Lata podzielne przez 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

Lata podzielne przez 4:

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

Lata podzielne przez 100:

[12]\d00

Nie można podzielić przez 100:

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

Lata podzielne przez 100, ale nie przez 400:

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

Podzielna przez 4, ale nie przez 100:

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

Lata przestępne:

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

Nie można podzielić przez 4:

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

To nie jest rok przestępny:

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

Ważny miesiąc i dzień z wyłączeniem lutego (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))

Luty z 28 dniami:

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

Luty z 29 dniami:

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

Ważna data:

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

Więc masz to wyrażenie regularne dla dat między 1 stycznia 1000 a 31 grudnia 2999 w formacie RRRR-MM-DD.

Podejrzewam, że można to trochę skrócić, ale zostawię to komuś innemu.

To będzie pasować do wszystkich ważnych dat. Jeśli chcesz, aby był ważny tylko wtedy, gdy zawiera tylko jedną datę i nic więcej, zawiń go w ten ^( )$sposób:

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

Jeśli chcesz, aby była to opcjonalna data (tj. Może być pusta lub ważna), dodaj ^$|na początku, tak jak poniżej :

^$|^(((((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])))))$
Graham
źródło
8
To heroiczne wyrażenie i bardzo dobrze wyjaśnione.
ambient
Czy masz mocny dowód, że przejdzie każdy ważny przypadek i zawiedzie w każdym nieważnym przypadku?
Md Ashraful Islam
@Md Ashraful Islam No
Graham
@Graham Chociaż nie ma problemu, używamy go na naszej stronie internetowej. Mam nadzieję, że żaden problem nie wystąpi.
Md Ashraful Islam
@Md Ashraful Islam - My również z niego korzystamy i do tej pory nie mieliśmy z nim żadnych problemów
Graham
18

Możesz to zrobić w ten sposób:

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

ale lepiej użyj tego:

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

w tym przypadku otrzymasz obiekt, który jest łatwiejszy w użyciu niż zwykłe łańcuchy.

k102
źródło
2
Zastosowana tutaj technika dateTime zwróci wartość true dla daty takiej jak 2016-05-44, która nie jest rzeczywistą datą
nonybrighto
To nie jest dobry przykład, zwłaszcza jeśli chcesz umówić się na randkę (Ymd). Przykład: 0175-44-19927przejdzie.
Attila Naghi
7

Wiem, że to stare pytanie. Ale myślę, że mam dobre rozwiązanie.

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

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

Możesz tego spróbować. Jeśli zmienisz datę na 21.02.2016, echo będzie fałszywe. A jeśli później zmienisz format na dmY, echo będzie prawdziwe.

Dzięki temu prostemu kodowi powinieneś być w stanie sprawdzić, który format daty jest używany, bez sprawdzania go przez wyrażenie regularne.

Może znajdzie się osoba, która przetestuje to w każdym przypadku. Ale myślę, że mój pomysł jest ogólnie ważny. Wydaje mi się to logiczne.

Micha93
źródło
Myślę, że nie potrzebujesz daty () wokół $ date w linii if. if (date ($ format, strtotime ($ date)) == $ date) - powinno wystarczyć
iateadonut
7

Możesz użyć preg_match z funkcją 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;
Jonathan Muller
źródło
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 wymaga / lub innego znaku jako separatora.

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

powinieneś również sprawdzić ważność tej daty, aby nie skończyć z czymś takim jak 9999-19-38

bool checkdate ( int $month , int $day , int $year )
marianboda
źródło
3

Możesz to również zrobić w ten sposób:

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

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

}

Spowoduje to nie tylko sprawdzenie formatu, ale także poprawność daty własnej, ponieważ DateTimeutworzy tylko prawidłowe daty i musi to być zgodne z danymi wejściowymi.

kasimir
źródło
3

możesz użyć

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
Jacek
źródło
2

Sprawdź i potwierdź YYYY-MM-DDdatę w jednym wyciągu liniowym

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

Wynik będzie:

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)

Dozwolone są dni i miesiące bez wiodącego zera. Jeśli nie chcesz na to zezwalać, wyrażenie regularne powinno wyglądać następująco:

"/^(\d{4})-(\d{2})-(\d{2})$/"
Vladislav Savchuk
źródło
2

Prawdopodobnie komuś się przyda:

$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
manh Nguyen
źródło
'1996-11-31 24:00'); // truenaprawdę? Co więcej, czasami jest 61 sekund w minucie, patrz: en.wikipedia.org/wiki/Leap_second
Toto
1

Jeśli chcesz dopasować ten typ daty, użyj:

preg_match("~^\d{4}-\d{2}-\d{2}$~", $date)
ujovlado
źródło
1

Powinno to powiedzieć, czy format jest prawidłowy i czy data wejściowa jest prawidłowa.

    $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';
    }
Kenzo
źródło
1

Jeśli to pomoże, oto wyrażenie regularne dla formatu jnY (rok musi być większy niż 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
}
Filip
źródło
1

Format 1: $ format1 = "2012-12-31";

Format 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;
}
Hasib Kamal
źródło
1

Funkcja do walidacji ogólnego formatu daty:

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

Przykład wykonania:

var_dump(validateDate('2021-02-28')); // true
var_dump(validateDate('2021-02-29')); // false
Sharad Pawar
źródło
Prosimy o umieszczanie odpowiedzi zawsze w kontekście, a nie tylko wklejanie kodu. Więcej informacji znajdziesz tutaj .
Zmień
0

Wszystko zależy od tego, jak rygorystyczna ma być ta funkcja. Na przykład, jeśli nie chcesz zezwolić na miesiące powyżej 12 i dni powyżej 31 (niezależnie od miesiąca, który wymagałby napisania logiki daty), może to stać się dość skomplikowane:

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

Osobiście po prostu wybrałbym: /^([0-9]{4}\-([0-9]{2}\-[0-9]{2})$/

Ariaan
źródło
4
To wyrażenie regularne jest niepotrzebnie skomplikowane. 0[1-9]|1[0-2]odpowiada miesiącowi 01-12 i 0[1-9]|[12][0-9]|3[01]dniu 01-31.
estrar
Przepraszam, gdy wymiotuję
AlxVallejo
0

Aby pracować z datami w php, powinieneś postępować zgodnie ze standardem php, aby podane wyrażenie regularne zapewniło, że masz prawidłową datę, która może działać z PHP.

    preg_match("/^([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/",$date)
Pratik Soni
źródło
Twój rgex jest zły, nie będzie pasował, 1980-01-01ale będzie pasował2100-02-29
Toto
0

Ta metoda może być przydatna do sprawdzania poprawności daty w PHP. Obecna metoda dotyczy formatu mm / dd / rrrr. Musisz zaktualizować sekwencję parametrów w checkdate zgodnie z formatem i ogranicznikiem w rozstrzeleniu .

    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;
        }
    }
Amit Garg
źródło
0

[Jeśli używasz Symfony 4.1.2, spróbuj tego] [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');
        }
DIDIT B
źródło
0

Z Laravel 5.7 i formatu daty, czyli: 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);
}
Mexidense
źródło
0

Szukałem "jak sprawdzić datę" i znalazłem to rozwiązanie, jego stara, ale udostępnię poniżej metodę, której można użyć do sprawdzenia daty w php,

checkdate('01', '31', '2019')
Parvez Alam
źródło