php cheque para una fecha válida, extrañas conversiones de fecha
Pregunta
¿Hay alguna manera de verificar si una fecha / hora es válida? Pensaría que sería fácil de verificar:
$date = '0000-00-00';
$time = '00:00:00';
$dateTime = $date . ' ' . $time;
if(strtotime($dateTime)) {
// why is this valid?
}
lo que realmente me molesta es esto:
echo date('Y-m-d', strtotime($date));
da como resultado: " 1999-11-30 " ;,
¿eh? Pasé de 75 a 1999-11-30 ???
Sé que podría hacer una comparación para ver si la fecha es cualquiera de esos valores es igual a la fecha que tengo, pero no es una forma muy robusta de verificar. ¿Hay una buena manera de verificar si tengo una fecha válida? ¿Alguien tiene una buena función para verificar esto?
Editar: La gente pregunta qué estoy ejecutando: Ejecución de PHP 5.2.5 (cli) (construido: 23 de julio de 2008 11:32:27) en Linux localhost 2.6.18-53.1.14.el5 # 1 SMP Wed Mar 5 11:36:49 EST 2008 i686 i686 i386 GNU / Linux
Solución
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;
}
?>
Otros consejos
Como se menciona aquí: https://bugs.php.net/bug.php? id = 45647
Aquí no hay ningún error, 00-00-00 significa 2000-00-00, que es 1999-12-00, que es 1999-11-30. Ningún error, perfectamente normal.
Y, como se muestra en algunas pruebas, el comportamiento esperado es retroceder hacia atrás, aunque sea un poco inquietante:
>> 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'
fecha de eco ('Y-m-d', strtotime ($ date));
da como resultado: " 1999-11-30 "
El resultado de strtotime
es 943920000 - este es el número de segundos, aproximadamente, entre época de Unix (base desde la cual se mide el tiempo) hasta 1999-11-30.
Hay un documentado error de mysql en mktime (), localtime (), strtotime ()
, todos devuelven este valor impar cuando intentas un tiempo pre-epoch (incluido " 0000-00-00 00: 00: 00 "). Hay un debate en el hilo vinculado sobre si esto es realmente un error:
Desde que se inició la marca de tiempo desde 1970, no creo que se suponga que Trabajar de todas formas.
A continuación se muestra una función que utilizo para convertir los tiempos de las fechas, como los anteriores, en una marca de tiempo para las comparaciones, etc., que puede ser de alguna utilidad para usted, para las fechas más allá 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);
}
No esperes resultados coherentes cuando estés fuera de rango:
cf strtotime
cf Gnu Calendar-date-items .html
" Para meses numéricos, la norma ISO 8601 formato & # 8216; año-mes-día & # 8217; esta permitido, donde año es cualquier número positivo, mes es un número entre 01 y 12 , y día es un número entre 01 y 31 . UNA el cero inicial debe estar presente si una el número es menor que diez. "
Así que '0000-00-00' da resultados extraños, ¡eso es lógico!
" Además, no todos las plataformas soportan marcas de tiempo negativas, por lo tanto, su intervalo de fechas puede ser Limitado a no antes que el Unix. época . Esto significa que, por ejemplo, % e,% T,% R y% D (podría haber más) y fechas anteriores a enero 1, 1970 no funcionará en Windows, algunos Distribuciones de Linux, y algunos otros sistemas operativos . "
cf strftime
Use la función checkdate (más robusta):
mes: El mes está comprendido entre 1 y 12 inclusive .
día: El día está dentro del número permitido de días para el dado mes. Se toman años bisiestos en consideración.
año: El año es entre 1 y 32767 inclusive .
Esta versión permite que el campo esté vacío, tiene fechas en formato mm / dd / aa o mm / dd / aaaa, permite horas de un solo dígito, agrega am / pm opcional y corrige algunas fallas sutiles en la coincidencia de tiempo .
Todavía permite algunos tiempos patológicos como '23: 14 AM '.
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 solo quieres manejar una conversión de fecha sin la hora para un campo de fecha de mysql, puedes modificar este gran código como lo hice yo. En mi versión de PHP sin realizar esta función, obtengo " 0000-00-00 " cada vez. Molesto.
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
Acabo de cambiar la respuesta de Martin, que validará cualquier tipo de fecha y volverá en el formato que desee.
Solo cambia el formato editando debajo de la línea 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" ;
}
}
?>
He utilizado el siguiente código para validar las fechas que provienen de las aplicaciones 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;
}
?>