vérification php pour une date valide, conversions de date étranges
Question
Existe-t-il un moyen de vérifier si une date / heure est valide? Vous penseriez que ce serait facile à vérifier:
$date = '0000-00-00';
$time = '00:00:00';
$dateTime = $date . ' ' . $time;
if(strtotime($dateTime)) {
// why is this valid?
}
Ce qui me rend vraiment, c'est ceci:
echo date('Y-m-d', strtotime($date));
entraîne: "1999-11-30",
hein? je suis passé de 0000-00-00 à 1999-11-30 ???Je sais que je pourrais faire une comparaison pour voir si la date est l'une de ces valeurs est égale à la date que j'ai mais ce n'est pas un moyen très robuste de vérifier. Y a-t-il un bon moyen de vérifier si j'ai une date valide? Quelqu'un at-il une bonne fonction pour vérifier cela?
Modifier: Les gens demandent ce que je cours: Exécution de PHP 5.2.5 (cli) sous Linux localhost 2.6.18-53.1.14.el5 # 1 SMP mer 5 mar 11:36:49 EST 2008 i686 i686 i386 GNU / Linux
La solution
De php.net
<?php
function isValidDateTime($dateTime)
{
if (preg_match("/^(\d{4})-(\d{2})-(\d{2}) ([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/", $dateTime, $matches)) {
if (checkdate($matches[2], $matches[3], $matches[1])) {
return true;
}
}
return false;
}
?>
Autres conseils
Comme mentionné ici: https://bugs.php.net/bug.php? id = 45647
Il n’ya pas de bogue ici, 00-00-00 signifie 2000-00-00, c’est-à-dire 1999-12-00, qui est 1999-11-30. Aucun bug, parfaitement normal.
Et comme le montrent quelques tests, revenir en arrière est un comportement attendu, même si un peu dérangeant:
>> date('Y-m-d', strtotime('2012-03-00'))
string: '2012-02-29'
>> date('Y-m-d', strtotime('2012-02-00'))
string: '2012-01-31'
>> date('Y-m-d', strtotime('2012-01-00'))
string: '2011-12-31'
>> date('Y-m-d', strtotime('2012-00-00'))
string: '2011-11-30'
echo date ('Y-m-d', strtotime ($ date));
entraîne: "1999-11-30"
Le résultat de strtotime
est 943920000 - nombre de secondes, approximativement, entre époque Unix (base à partir de laquelle le temps est mesuré) au 1999-11-30.
Un bogue mysql est documenté. sur mktime (), localtime (), strtotime ()
renvoient tous cette valeur impaire lorsque vous essayez une heure antérieure à la période (y compris "0000-00-00 00: 00: 00"). Il y a un débat sur le fil lié pour savoir s'il s'agit réellement d'un bogue:
Puisque l'horodatage a commencé à partir de 1970, je ne pense pas qu'il soit supposé travailler de toute façon.
Ci-dessous, une fonction que j’utilise pour convertir dateTimes, comme celle ci-dessus, en un horodatage pour les comparaisons, etc., qui peut vous être utile pour des dates au-delà de "0000-00-00 00: 00: 00".
/**
* Converts strings of the format "YYYY-MM-DD HH:MM:SS" into php dates
*/
function convert_date_string($date_string)
{
list($date, $time) = explode(" ", $date_string);
list($hours, $minutes, $seconds) = explode(":", $time);
list($year, $month, $day) = explode("-", $date);
return mktime($hours, $minutes, $seconds, $month, $day, $year);
}
Ne vous attendez pas à des résultats cohérents lorsque vous êtes hors de portée:
cf strtotime
cf Gnu Calendar-date-items .html
"Pour les mois numériques, l'ISO 8601 le format «année-mois-jour» est autorisé, où année est un nombre positif, mois est un nombre compris entre 01 et 12 , et le jour est un nombre compris entre 01 et 31 . UNE le zéro principal doit être présent si un le nombre est inférieur à dix. "
Donc, '0000-00-00' donne des résultats étranges, c'est logique!
" En outre, pas tous les plateformes supportent des horodatages négatifs, par conséquent, votre plage de dates peut être limité à pas plus tôt que l'Unix époque . Cela signifie par exemple que % e,% T,% R et% D (il pourrait y avoir plus) et dates antérieures à janvier 1, 1970 ne fonctionnera pas sous Windows, certains Distributions Linux et quelques autres systèmes d'exploitation . "
cf strftime
Utilisez plutôt la fonction checkdate (plus robuste):
mois: Le mois est compris entre 1 et 12 inclus .
jour: Le jour est dans le nombre de jours autorisé pour le donné mois. Les années bissextiles sont prises en considération.
année: L'année est comprise entre 1 et 32767 .
Cette version permet que le champ soit vide, comporte des dates au format mm / jj / aa ou mm / jj / aaaa, autorise des heures à un chiffre, ajoute facultatif am / pm et corrige quelques failles dans la correspondance temporelle. .
Autorise toujours certains moments pathologiques comme '23: 14 heures '.
function isValidDateTime($dateTime) {
if (trim($dateTime) == '') {
return true;
}
if (preg_match('/^(\d{1,2})\/(\d{1,2})\/(\d{2,4})(\s+(([01]?[0-9])|(2[0-3]))(:[0-5][0-9]){0,2}(\s+(am|pm))?)?$/i', $dateTime, $matches)) {
list($all,$mm,$dd,$year) = $matches;
if ($year <= 99) {
$year += 2000;
}
return checkdate($mm, $dd, $year);
}
return false;
}
Si vous voulez juste gérer une conversion de date sans l'heure pour un champ de date mysql, vous pouvez modifier ce code génial comme je l'ai fait. Sur ma version de PHP sans utiliser cette fonction, le message "0000-00-00" est affiché. à chaque fois. Ennuyeux.
function ConvertDateString ($DateString)
{
list($year, $month, $day) = explode("-", $DateString);
return date ("Y-m-d, mktime (0, 0, 0, $month, $day, $year));
}
<?php
function is_valid_date($user_date=false, $valid_date = "1900-01-01") {
$user_date = date("Y-m-d H:i:s",strtotime($user_date));
return strtotime($user_date) >= strtotime($valid_date) ? true : false;
}
echo is_valid_date("00-00-00") ? 1 : 0; // return 0
echo is_valid_date("3/5/2011") ? 1 : 0; // return 1
Je viens de changer la réponse martin ci-dessus, ce qui validera tout type de date et renverra dans le format de votre choix.
Changez simplement le format en éditant sous la ligne de script strftime ("10-10-2012", strtotime ($ dt));
<?php
echo is_date("13/04/10");
function is_date( $str ) {
$flag = strpos($str, '/');
if(intval($flag)<=0){
$stamp = strtotime( $str );
} else {
list($d, $m, $y) = explode('/', $str);
$stamp = strtotime("$d-$m-$y");
}
//var_dump($stamp) ;
if (!is_numeric($stamp)) {
//echo "ho" ;
return "not a date" ;
}
$month = date( 'n', $stamp ); // use n to get date in correct format
$day = date( 'd', $stamp );
$year = date( 'Y', $stamp );
if (checkdate($month, $day, $year)) {
$dt = "$year-$month-$day" ;
return strftime("%d-%b-%Y", strtotime($dt));
//return TRUE;
} else {
return "not a date" ;
}
}
?>
J'ai utilisé le code suivant pour valider les dates provenant d'applications ExtJS.
function check_sql_date_format($date) {
$date = substr($date, 0, 10);
list($year, $month, $day) = explode('-', $date);
if (!is_numeric($year) || !is_numeric($month) || !is_numeric($day)) {
return false;
}
return checkdate($month, $day, $year);
}
<?php
function is_date( $str ) {
$stamp = strtotime( $str );
if (!is_numeric($stamp)) {
return FALSE;
}
$month = date( 'm', $stamp );
$day = date( 'd', $stamp );
$year = date( 'Y', $stamp );
if (checkdate($month, $day, $year)) {
return TRUE;
}
return FALSE;
}
?>