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

Оставлять комментарии могут только зарегистрированные пользователи

Комментарии  

Vizer
# Vizer 05.06.2013 14:13
Либо использовать нативный класс DateTime
Иван Бунин
# Иван Бунин 29.12.2018 10:21
Так не проще?
function timeStamp($date, $format = 'd/m/Y')
{
$d = DateTime::createFromFormat($format, $date);
return $d->getTimestamp();
}