verificação php uma data válida para, conversões de data estranhas
Pergunta
Existe uma maneira de verificar para ver se a data / hora é válida você pensaria que estes seriam fácil de verificar:
$date = '0000-00-00';
$time = '00:00:00';
$dateTime = $date . ' ' . $time;
if(strtotime($dateTime)) {
// why is this valid?
}
o que realmente me deixa é a seguinte:
echo date('Y-m-d', strtotime($date));
resulta em: "1999-11-30",
hein? Eu fui de 0000-00-00 a 1999-11-30 ???
Eu sei que eu poderia fazer comparação para ver se a data é um desses valores é igual à data eu tenho, mas não é uma maneira muito robusta para verificar. Existe uma boa maneira de verificar para ver se eu tenho uma data válida? Alguém tem uma boa função para verificar isso?
Edit: As pessoas estão perguntando o que eu estou correndo: Rodando o PHP 5.2.5 (CLI) (construído Julho 23, 2008 11:32:27) no Linux localhost 2.6.18-53.1.14.el5 # 1 SMP Wed 05 de marco 11:36:49 EST 2008 i686 i686 i386 GNU / Linux
Solução
A partir 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;
}
?>
Outras dicas
Como mencionado aqui: https://bugs.php.net/bug.php? id = 45647
Não há erro aqui, 00-00-00 meios 2000-00-00, que é 1999-12-00, que é 1999-11-30. Sem bug, perfeitamente normal.
E como mostrado com alguns testes, rolando comportamento trás é esperado, se um pouco 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'
eco data ( 'Y-m-d', strtotime ($ data));
resulta em: "1999-11-30"
O resultado da strtotime
é 943920000 - este é o número de segundos, mais ou menos, entre a época Unix (base a partir dos quais o tempo é medido) para 1999-11-30.
Há um documentado mysql bug em mktime(), localtime(), strtotime()
tudo devolver este valor ímpar quando você tenta um tempo pré-época (incluindo "0000-00-00 00:00:00"). Há algum debate sobre o fio ligado para saber se este é realmente um erro:
Uma vez que o carimbo de tempo é iniciado de 1970, eu não acho que deveria trabalho em qualquer forma.
Abaixo está uma função que eu use para converter datetimes como o acima para um timestamp para comparações, etc, que podem ser de alguma utilidade para você, para datas além "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);
}
Não espere resultados coerentes quando você está fora do intervalo:
Gnu Calendário-data-itens .html
"Durante meses numéricos, a ISO 8601 formato ‘ano-mês-dia’ é permitido, onde no ano é qualquer número positivo, mês é um número entre 01 e 12 e dia é um número entre 01 e 31 . UMA zero à esquerda deve estar presente se um número é inferior a dez. "
Assim, '0000-00-00' dá resultados estranhos, isso é! Lógico
"Além disso, não é tudo plataformas suportam timestamps negativos, portanto, o intervalo de datas pode ser limitado a não mais cedo do que o Unix época . Isto significa que, por exemplo, % E,% T, R e%% D (que pode ser mais) e datas anteriores a Janeiro 1 de 1970 não irá funcionar no Windows, alguns distribuições Linux, e alguns outros sistemas operacionais . "
Use a função checkdate vez (mais robusto):
mês: O mês é entre 1 e 12 inclusive .
dia: O dia está dentro do número permitido de dias para o dado mês. Leap Year s são tomadas em consideração.
ano: O ano é entre 1 e 32767 inclusiva .
Esta versão permite o campo estar vazio, tem datas em mm / dd / aa ou dd formato mm / / aaaa, permitem horas de um único dígito, acrescenta opcional am / pm, e corrige algumas falhas sutis no jogo do tempo .
Ainda permite que algumas vezes 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;
}
Se você quiser apenas para lidar com uma conversão de data sem a hora de um campo de data mysql, você pode modificar este código grande como eu fiz. Na minha versão do PHP sem executar essa função eu recebo "0000-00-00" cada vez. Irritante.
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
I foram apenas mudando a resposta martin acima, que irá validar qualquer tipo de data e retorno no formato que você quiser.
Apenas alterar o formato editando abaixo da linha de roteiro strftime ( "2012/10/10", 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" ;
}
}
?>
Eu tenho usado o seguinte código para datas Validar provenientes de aplicações 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;
}
?>