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?
php
regex
date-format
cosmicsafari
źródło
źródło
date("Y-m-d", strtotime("2012-09-12"))=="2012-09-12";
lub PHPcheckdate ( int $month , int $day , int $year )
.Odpowiedzi:
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; }
źródło
return (bool)preg_match("/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/",$date);
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 !== false
zapewnia, że data może być analizowana w określonym formacie, aarray_sum
sztuczka 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
explode
icheckdate
: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:
explode
jest ograniczona do zwrotu 3 żetonów (więc jeśli wartość wejściowa to „1-2-3-4”,$d
zmieni 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_pad
jest używany (z wartością domyślną, która spowodujecheckdate
niepowodzenie), aby upewnić się, że zostanie zwrócona wystarczająca liczba elementów, aby jeśli wejście to "1-2"list()
, nie wyemituje powiadomieniaźródło
DateTime
i nigdy nie słyszałem ocheckdate
... wstyd mi.DateTime
też może to zrobić. Właśnie skończyłem opracowywać odpowiedź, spójrz ponownie, jeśli chcesz.getLastErrors
?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
źródło
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])))))$
źródło
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.
źródło
0175-44-19927
przejdzie.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.
źródło
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;
źródło
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 )
źródło
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ż
DateTime
utworzy tylko prawidłowe daty i musi to być zgodne z danymi wejściowymi.źródło
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
źródło
Sprawdź i potwierdź
YYYY-MM-DD
datę w jednym wyciągu liniowymfunction 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})$/"
źródło
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
źródło
'1996-11-31 24:00'); // true
naprawdę? Co więcej, czasami jest 61 sekund w minucie, patrz: en.wikipedia.org/wiki/Leap_secondJeśli chcesz dopasować ten typ daty, użyj:
preg_match("~^\d{4}-\d{2}-\d{2}$~", $date)
źródło
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'; }
źródło
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 }
źródło
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; }
źródło
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
źródło
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})$/
źródło
0[1-9]|1[0-2]
odpowiada miesiącowi 01-12 i0[1-9]|[12][0-9]|3[01]
dniu 01-31.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)
źródło
1980-01-01
ale będzie pasował2100-02-29
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; } }
źródło
[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'); }
źródło
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); }
źródło
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')
źródło