2013-11-04 10 views
7

Sto cercando di rendere un validatore di espressioni regolari. Il problema che sto avendo è che sto usando un campo di input con il tipo "date", che funziona come un fascino in Chrome; apre un calendario simile a Chrome, ma nel resto non fa nulla, quindi ho deciso di inserire un input manuale della data per il resto.Regex per convalidare la data in PHP utilizzando il formato come AAAA-MM-GG

Questo è il mio messaggio di errore di lancio (che sto cercando formato AAAA-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.'; 
} 

So che ci sono un sacco di esempi su questo, ma ho provato come 20 e ho già non potrei risolverlo Forse mi manca qualcosa.

Ecco il campo di inserimento, se un po 'rilevanti:

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

Perché non esplodere con - e utilizzare invece checkdate()? –

+0

Esiste una procedura standard? L'ho trovato in un altro post ma non ha funzionato per me. Cordiali saluti, voglio lasciarli inserire come YYYY/MM/DD o YYYY.MM.DD o YYYY-MM-DD. Per non trattenerli troppo. – Cataneo

+3

Sarebbe più semplice fornire 3 caselle separate '' con una lunghezza massima appropriata e una convalida di sola cifra che viene concatenata nel formato corretto sul back-end? È possibile aggiungere listener ad ogni casella di input per passare alla successiva se una persona ha premuto 2 cifre con la pressione di un tasto. L'utente non dà ratti su quale formato è necessario e li frusterà al meglio solo se non è il loro formato nativo personale – MonkeyZeus

risposta

10

L'espressione regolare non ha funzionato perché era senza escape delimitatore /.

L'espressione regolare che avrebbe convalidare data in formato YYYY-MM-DD come segue:

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

Si convaliderà che l'anno inizia con 19 o 20, che il mese non è maggiore di 12 e non è uguale 0 e che il giorno non è maggiore di 31 e non è uguale a 0.

Example Online

Usando il tuo esempio iniziale, si potrebbe verificare in questo modo:

$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

Sì, questo ha funzionato bene. Ho usato così tante varianti della regex che devo averlo modificato male. Occhi fantastici hai lì Ilia Rostovtsev. – Cataneo

13

Non usare espressioni regolari per questo, è possibile ottenere lo stesso risultato utilizzando 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"); 
} 

si può leggere di più qui:

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

Ho Comunque, sembra che il problema non sia affatto correlato a PHP.

PHP viene eseguito sul back-end e sembra che tu abbia un problema di front-end.

Dubito anche che il problema sia il tipo di input che si utilizza. Se un browser non supporta il tipo di input specificato, il valore predefinito è il testo. Vedere qui:

http://jsfiddle.net/FKGCA/

Il mio browser non sa cosa l'<input type="whatever" /> è, quindi il valore predefinito il tipo di ingresso per "testo". Se avvolgo quei 4 ingressi in un tag <form action="myForm.php" method="POST"></form>, il browser invia gli input al server perché al server non interessa/sa se gli input sono nascosti, i pulsanti di opzione, i testi, o la password. I server ricevono solo dati grezzi.

Più che probabile, il tuo problema è con il tuo Javascript, e non con il tuo PHP. Prova a vedere se il browser che non visualizza il tuo widget ti dice che c'è un errore di qualche tipo nella tua pagina.

Safari e Firefox dispongono di strumenti di sviluppo/debug, non così sicuri di IE.

+0

Era esattamente quello che stavo affermando. Il "widget" funziona in Chrome e viene convertito in un tipo di input di testo negli altri. Questo è esattamente quello che sto cercando di convalidare. Ho il formato della data e divido il campo in tre e andrò da lì. – Cataneo

+1

getcha, per casi come questo è quando jQuery torna utile. Altrimenti, dovrai testare il supporto: http://diveintohtml5.info/detect.html#input-types e se non è supportato. Dovrai utilizzare le alternative basate su javascript (come jQuery) – ILikeTacos

0

controllare e convalidare YYYY-MM-DD data in un unico prospetto linea

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

See i dettagli nella mia risposta here.

Non utilizzare ciecamente DateTime::createFromFormat per convalidare le date. Prendiamo data inesistente 2018-02-30 e vediamo:

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

Sì, restituisce true, non false come si potrebbe previsto. Più interessante:

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

anche true ... Quindi, convalida solo il numero di cifre. Un altro tentativo:

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

Finalmente false.

quello che sta succedendo qui possiamo vedere da questo frammento:

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

Come si può vedere quando si passa inesistente 2018-02-30, l'oggetto contiene DateTime2018-03-02. Suppongo che sia perché febbraio 2018 ha 28 giorni, cioè la data massima è 2018-02-28 e quando passiamo il giorno 30, createFromFormat aggiunge solo 30 giorni allo 2018-02-01 e crea una nuova data senza alcuna convalida della data precedente.

Problemi correlati