В php есть замечательная функция работы со временем strtotime. Она преобразует строковое представление даты в UNIXTIME формат(количество секунд, прошедшее с 1-го января 1970-го года). Удобна она прежде всего тем, что в нее можно подавать данные, введенные пользователем в форме, к примеру, дату рождения. На выходе мы получим удобный unixtime, с помощью которого можно проводить различные валидные сортировки по дате.
Приведу пример:
echo strtotime('8-12-1986'); // вернет 534366000
что эквивалентно
echo mktime(0,0,0,12,8,1986);
Но что если ваш пользователь пришлет на вход функции такой формат '8 12 1986'. В этом случае
echo strtotime('8 12 1986'); // вернет false
Функции просто не понятно, что здесь день, что здесь месяц, а что год. Как решить данную проблему? Как показать php формат введенной даты?
Мне часто задавали подобные вопросы. Но сам я до определенного момента с этим не сталкивался, пока не случилось парсить один сайт, притом нужно было брать время с этого сайта. Сначала я попробовал strtotime, но время на том сайте было в невалидном формате. Поэтому на свет родилась вот такая функция:
function strtotimef($stime,$format=''){ if( trim($format)=='' )return strtotime($stime); $artimer = array( 'd'=>'([0-9]{2})', 'j'=>'([0-9]{1,2})', 'F'=>'([a-z]{3,10})', 'm'=>'([0-9]{2})', 'M'=>'([a-z]{3})', 'n'=>'([0-9]{1,2})', 'Y'=>'([0-9]{4})', 'y'=>'([0-9]{2})', 'i'=>'([0-9]{2})', 's'=>'([0-9]{2})', 'h'=>'([0-9]{2})', 'H'=>'([0-9]{2})', '#'=>'\\#', ' '=>'\\s', ); $arttoval = array( 'j'=>'d', 'f'=>'m', 'n'=>'m', ); $reg_format = '#'.strtr($format,$artimer).'#Uis'; if( preg_match_all('#[djFmMnYyishH]#',$format,$list) and preg_match($reg_format,$stime,$list1) ){ $item = array('h'=>'00','i'=>'00','s'=>'00','m'=>1,'d'=>1,'y'=>1970); foreach($list[0] as $key=>$valkey){ if( !isset($arttoval[strtolower($valkey)]) ) $item[strtolower($valkey)] = $list1[$key+1]; else $item[$arttoval[strtolower($valkey)]] = $list1[$key+1]; } return strtotime($item['h'].':'.$item['i'].':'.$item['s'].' '.$item['d'].' '.$item['m'].' '.$item['y']); }else return false; }
По второй строчке видно, что если не вводить формат, то она ведет себя точно так же, как и нативная strtotime. Но если мы ввели формат, то введенная дата распарсивается по нему.
Приведу несколько примеров:
echo strtotimef('8-12-1986); // вернет 534366000 echo strtotimef('8121986','jmY'); // вернет 534366000 echo strtotimef('8 Dec 1986,'j M Y'); // вернет 534366000 echo strtotimef('12 8 1986,'m j Y'); // вернет 534366000
Ну и самое вкусное:
echo strtotimef('<div> 08 December 1986</div>','d F Y'); // вернет 534366000
Однако, формат накладывает и определенную долю ответственности за введенные данные, к примеру, если данные валидны, но не соответствуют формату, то обычная strtotime их съест. А вот strtotimef этого себе позволить не может.
echo strtotimef('8 12 1986','j MY '); // данные валидны, но не соответствуют формату, поэтому вернет false
Тут важно обратить внимание на этот самый формат, он представляет собой регулярное выражение с автозаменой значащих символов. Таких символом не много:d j F m M n Y y i s h H.
Остановимся подробнее на каждом из них:
d - день месяца, с ведущим нулем . Может принимать значения 01-31
j - день месяца, без нуля. Может принимать значения 1-31
F - полное название месяца на английском. Может принимать значения January-December
n - номер месяца, без нуля. Может принять значение 1-12
M - краткое название месяца на английском (3 буквы). Может принимать значения Jan-Dec
m - номер месяца, с ведущим нулем. Может принять значение 01-12
Y - полное цифровое представление года, к примеру 1999 или 2005
y - 2-х численное представление года, к примеру 99 или 05
i - минуты с ведущим нулем. Может принимать значения 00-59
s - секунды с ведущим нулем. Может принимать значения 00-59
h - 12-часовой формат часа с ведущими нулями. Может принимать значения 01-12
H - 24-часовой формат часа с ведущими нулями. Может принимать значения 00-23
Это все опции, которые я реализовал в данной функции. Просто думаю мало кому могут понадобиться к примеру u - микросекунды. Если вам все же они нужны, напишите об этом в комментариях. Также функция должным образом не протестирована, поэтому буду рад критике.
Комментарии
function timeStamp($date, $format = 'd/m/Y')
{
$d = DateTime::createFromFormat($format, $date);
return $d->getTimestamp();
}