2010-03-26 9 views
57

Tengo una cadena y necesito averiguar si es una marca de tiempo Unix o no, ¿cómo puedo hacer eso de manera efectiva?Comprueba si la cadena es una marca de tiempo de Unix

Encontré this thread en Google, pero no tiene una respuesta muy sólida, me temo. (Y sí, archivé la pregunta del cartel original en el hilo antes mencionado).

+0

desde leer el hilo, diría que la respuesta corta es no. Es muy posible que pueda verificar algo que definitivamente no es válido pero que es válido, no lo parece. – PurplePilot

+0

¿Puede agregar alguna explicación adicional sobre por qué necesita validar la cadena o qué está planeando hacer con ella, una vez que se haya validado? – Gordon

Respuesta

77

Ok, después de tocar el violín con esto desde hace algún tiempo, me retiro de la solución con date('U') y mejor utilizar éste en su lugar:

function isValidTimeStamp($timestamp) 
{ 
    return ((string) (int) $timestamp === $timestamp) 
     && ($timestamp <= PHP_INT_MAX) 
     && ($timestamp >= ~PHP_INT_MAX); 
} 

Esta comprobación sólo devolverá verdadero si el dado $timestamp es una cadenay consiste únicamente en dígitos y un carácter negativo opcional. El número también debe estar dentro del rango de bits de un número entero (EDIT: actually unneeded as shown here).

var_dump(isValidTimeStamp(1)   ); // false 
var_dump(isValidTimeStamp('1')   ); // TRUE 
var_dump(isValidTimeStamp('1.0')  ); // false 
var_dump(isValidTimeStamp('1.1')  ); // false 
var_dump(isValidTimeStamp('0xFF')  ); // false 
var_dump(isValidTimeStamp('0123')  ); // false 
var_dump(isValidTimeStamp('01090')  ); // false 
var_dump(isValidTimeStamp('-1000000') ); // TRUE 
var_dump(isValidTimeStamp('+1000000') ); // false 
var_dump(isValidTimeStamp('2147483648') ); // false 
var_dump(isValidTimeStamp('-2147483649')); // false 

El cheque por PHP_INT_MAX es asegurar que la cadena puede ser utilizado correctamente por date y los gustos, por ejemplo, asegura que esto no suceda *:

echo date('Y-m-d', '2147483648'); // 1901-12-13 
echo date('Y-m-d', '-2147483649'); // 2038-01-19 

En sistemas de 64 bits del entero es por supuesto más grande que eso y la función ya no volverá falsa para "2147483648" y "-2147483649" pero para los grandes números correspondientes .


(*) Nota: No estoy seguro al 100%, el rango de bit corresponde con qué fecha se puede utilizar aunque

+1

I * think * timestamps negativos son válidos. 'time_t' está firmado en Linux al menos. – Yacoby

+1

No funcionó por un valor de 1276664400, probablemente debido a que el valor se volvió a pasar como una cadena en lugar de un número entero. –

+1

@jtyost Funciona según lo explicado y exigido por el OP. Comprueba si ** la cadena ** es una marca de tiempo de Unix válida. Al pasar en un ** entero ** obviamente no volverá verdadero. Al pasar en '" 1276664400 "' será. – Gordon

34

Como una marca de tiempo unix es un número entero, use is_int(). Sin embargo, como is_int() no funciona en cadenas, comprobamos si es numérico y su forma intergaláctica es la misma que su forma original. Ejemplo:

(is_numeric($stamp) && (int)$stamp == $stamp) 
+0

Para expresar marcas de tiempo con milisegundos, la marca de hora única también puede ser un punto flotante en algunas áreas, ¿verdad? –

+0

@Patrick Una marca de tiempo Unix suele ser un número entero debido a la precisión de coma flotante. Nunca me he encontrado representado como un número real. – Yacoby

+1

El OP tiene una cadena, por lo que is_int no funcionará. Tiene que ser is_numeric si hay alguno. – Gordon

1

¿Desea verificar si una cadena contiene un número alto?

is_numeric() es la clave

o convertirla en DateTime y hacer algunas comprobaciones con él como un rango de fechas esperado.

2

Esto no tiene en cuenta los tiempos negativos (antes de 1970) , ni tampoco representan rangos mayores (puede usar números enteros de 64 bits, de modo que una marca de tiempo puede representar un valor mucho después de 2038)

$valid = ctype_digit($str) && $str <= 2147483647; 
0

Otra posibilidad:

$date_arg = time(); 
$date_is_ok = ($date_arg === strtotime(date('c', $date_arg))); 
+1

¿Está validando $ date_arg contra sí mismo? ¿Cómo valida eso si otra cadena es una fecha? –

0
//if anything else than digits inside the string then your string is no timestamp 
    //in which case maybe try to get the timestamp with strtotime 

    if(preg_match('/[^\d]/', $str)) { 
     $str = strtotime($str); 

     if (false === $str) { 
      //conversion failed - invalid time - invalid row 
      return; 
     } 
    } 
4

esto se ve como el camino a seguir:

function is_timestamp($timestamp) { 
    if(strtotime(date('d-m-Y H:i:s',$timestamp)) === (int)$timestamp) { 
     return $timestamp; 
    } else return false; 
} 

también se puede añadir un is_numeric() comprobar y todo tipo de otros controles.
pero esto debería/podría ser lo básico.

+0

Este código funciona, pero lanzará un aviso si lo pasa más allá de una marca de tiempo válida. –

+0

¿De qué se trata el aviso? (He tenido un error tipográfico. ¡Usa d-m-Y en lugar de American m-d-Y!) puedes modificarlo con Lanzamientos de excepciones en cosas. –

+0

Es un E_NOTICE que ha pasado un valor no válido. El formateo de la fecha() no afecta esto.A algunas personas no les molestan los guiones que lanzan avisos y simplemente desactivan los informes de errores para ese nivel, pero muchos (incluido yo mismo) prefieren no lanzar ni silenciar ni siquiera los avisos de E_STRICT a menos que realmente tengamos que hacerlo. –

0

o

if ($startDate < strtotime('-30 years') || $startDate > strtotime('+30 years')) { 
    //throw exception 
} 
0

Si usted podría pensar para reemplazar solución this con is_numeric(), por favor considere que la función nativa de PHP proporciona falsos positivos para las cadenas de entrada como "1.1", "0123", "0xFF", que no son en formato de marca de tiempo.

2

Respuesta mejorada a @TD_Nijboer.

Esto evitará una excepción ser lanzado si la cadena suministrada no es un sello de tiempo:

function isTimestamp($timestamp) { 
    if(ctype_digit($timestamp) && strtotime(date('Y-m-d H:i:s',$timestamp)) === (int)$timestamp) { 
     return true; 
    } else { 
     return false; 
} 
7

me encontré con la misma pregunta y creado la siguiente solución para mi mismo, donde yo no tengo que lío con expresiones regulares o cláusulas if:

/** 
* @param string $string 
* @return bool 
*/ 
public function isTimestamp($string) 
{ 
    try { 
     new DateTime('@' . $string); 
    } catch(Exception $e) { 
     return false; 
    } 
    return true; 
} 
Cuestiones relacionadas