В php есть замечательная функция работы со временем strtotime. Она преобразует строковое представление даты в UNIXTIME формат(количество секунд, прошедшее с 1-го января 1970-го года). Удобна она прежде всего тем, что в нее можно подавать данные, введенные пользователем в форме, к примеру, дату рождения. На выходе мы получим удобный unixtime, с помощью которого можно проводить различные валидные сортировки по дате.
Приведу пример:
1 | echo strtotime ( '8-12-1986' ); // вернет 534366000 |
что эквивалентно
1 | echo mktime (0,0,0,12,8,1986); |
Но что если ваш пользователь пришлет на вход функции такой формат '8 12 1986'. В этом случае
1 | echo strtotime ( '8 12 1986' ); // вернет false |
Функции просто не понятно, что здесь день, что здесь месяц, а что год. Как решить данную проблему? Как показать php формат введенной даты?
Мне часто задавали подобные вопросы. Но сам я до определенного момента с этим не сталкивался, пока не случилось парсить один сайт, притом нужно было брать время с этого сайта. Сначала я попробовал strtotime, но время на том сайте было в невалидном формате. Поэтому на свет родилась вот такая функция:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | 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. Но если мы ввели формат, то введенная дата распарсивается по нему.
Приведу несколько примеров:
1 2 3 4 | 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 |
Ну и самое вкусное:
1 | echo strtotimef( '<div> 08 December 1986</div>' , 'd F Y' ); // вернет 534366000 |
Однако, формат накладывает и определенную долю ответственности за введенные данные, к примеру, если данные валидны, но не соответствуют формату, то обычная strtotime их съест. А вот strtotimef этого себе позволить не может.
1 | 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();
}