В 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 - микросекунды. Если вам все же они нужны, напишите об этом в комментариях. Также функция должным образом не протестирована, поэтому буду рад критике.

Рассказать друзьям

Добавить комментарий


Защитный код
Обновить

Комментарии   

0
Vizer
# Vizer 05.06.2013 14:13
Либо использовать нативный класс DateTime