Лично мне никогда не нравилось возится с датами и временем. Все эти created и modified уже набили оскомину. По-этому волей-неволей приходится с ними работать. Тут я постараюсь описать общие приемы от и до. Большую часть на оглядку статьи, которая в свое время мне очень помогла, забытого мною автора. Ссылкой поделится не смогу, но приблизительное содержание с моими комментариями и мыслям пожалуйста:
Unix системы оперируют с временем исходя из количества секунд, которые прошли с полночи 1 января 1970 года (так называемый Unix Epoch).
По-этому если мы выполним нечто подобное на:
<?php echo time(); ?>
то получим результат 1184447853
Это только что произошло 12:43 в субботу 14 июля 2007 года.
Это конечно хорошо, но какая мне польза от такого результата? Вполне конкретная, если честно. Во-первых, time() возвращает значение типа timestamp. Большое количество функций для работы с датой в PHP использует именно этот тип данных для своих аргументов. Во-вторых, есть такой нехилый бонус в том, что timestamp по сути является целом числом. Т.е. можно сохранять его в базе данных абсолютно не беспокоясь об преобразованиях к виду date/time полей. Причем в некоторых ситуаций такое хранение не то чтобы удобно, а опрадано.
В определенных ситуациях есть зачем. Чаще всего когда легче иметь дело с календарным представлением дат - представление даты пользователю как самый банальный пример. Или в той же базе данных гораздо легче работать с датой в виде 2007-07-14 чем 1198905820.
ОК, теперь мы знаем что и почем по поводу timestamp в Unix. Наверно начнем двигаться дальше и узнаем еще что-нибудь полезное.
PHP поддерживает два спобоба для представления timestamp в нечто более информативное. Первый зовется функцией date(). Эта функция принимает два аргумента. Первый - строка-шаблон, в которой содержится необходимое для результата форматирование, и второй - Unix timestamp. В строке-шаблоне вместо специально принятых символов поставляются необходимые данные из даты.
Допустим захотелось мне дату в виде "18ч01 воскресенье 21 мая". Для этого необходимо использовать специальный символ для каждого значения в строке, которое может изменятся. Таких специальных символов достаточно много - некоторые из них возвращают название месяца, день недели, год в 2 или 4 цифровом формате и т. п. Для нашего случае нам понадобятся следующие:
H - час в 24-часовой формат; т.е. от "00" до "23"
i - минуты; т.е. от "00" до "59"
l ('L' в нижнем регистре) - день недели, буквенный; например, "Friday"
d - день (число) месяца, 2 цифры с ведущим нулем, если необходимо; т. е. от "01" до "31"
F - полное название месяца; например, "January"
То есть наша строка будет выглядеть примерно таким образом: "Hчi l d F", а PHP-код примерно вот так:
<?php echo date( 'Hhi l d F', time() ); ?>
Если мы захотим использовать в выводе форматированной строки некоторые из специальных символов, то следует экранировать их обратной косой чертой.
Пример:
<?php echo date( 'Hhi l d F', time() ); ?>
Это первый вариант. Но если в форматирование входит строка из символов или даже целый абзац? Неужели необходимо экранировать каждый символ? Нет, потому что мы можем использовать другую функцию под названием strftime().
У strftime() есть два преимущества. Первое, которое я сейчас не собираюсь обсуждать, - это при вызванной setlocale() функции, вы получите имена месяцев в соответствии с региональными настройками. Второе - это то, что вы можете встраивать уже отформатированные данные в строку любого вида. И вам совсем не обязательно запоминать новые специальные символы, т. к. strftime() работает по таким же принципам как и date(), за исключением того, что каждый специальный символ должен быть экранирован знаком %. Так предыдущий пример будет выглядеть так:
<?php echo strftime( '%Hh %M %A %d %b', time() ); ?>
Возвращаемое значение будет таким же.
Это может выглядеть немного сложно, но представьте себе ситуацию, когда вам необходимо сказать: "Today is Sunday 21 May 2000. The time is somewhere close to 18h24." Использование экранирования с помощью будет немного занудным. Особенно когда длина такой строки перевалит за десяток слов.
Чуть раньше я упоминал 2 способа получить от timestamp что-нибудь полезное. Мы только что рассмотрели date() и strftime(). Способ номер 2 - это getdate(). Это функция принимает только один аргумент типа Unix timestamp и возвращает ассоциативный массив, содержащий информацию о дате.
Например
<?php $date_time_array = getdate( time() ); echo $date_time_array['weekday']; ?>
возвратит Воскресенье.
Кроме "weekday" наличествуют и другие части даты:
Так. Теперь мы можем создавать удобочитаемые дату и время. И что дальше? А дальше продолжим и рассмотрим некотрые часто встречающиеся задачи.
Очень часто приходится работать с данными, которые уже имеют какое-либо форматирование даты и/или времени. Далеко за примерами не ходить - тот же MySQL хранит DATE в виде 2007-07-14. Функция mktime() содержит в своих аргументах части даты и времени, которые необходимо возвратить в виде timestamp.
Формат этой функции таков:
int mktime(int hour, int minute, int second, int month, int day, int year, int [is_dst] );
Слева направо задается час, минуты, секунды, месяц, день и год. Последний аргумент указывает поправку на летнее время (1, если это период с поправкой на летнее время, 0 - если нет, -1 - если неизвестно). Для простоты я этот аргумент пропущу.
Пример:
<?php echo mktime( 0,0,0,14,07,2007); ?>
Мы обнулили часы, минуты и секунды, т. к. в нашем случае не знаем точного времени. Нули возвратят нам полночь, что вполне приемлимо. Конечно, я немного схалтурил, записав значение 2007-07-14 прямо в функции. Ну, ладно. Перепишем как надо:
<?php
$access_date = '2007-07-14';
// explode() функция разделяет строку другой строкой. В нашем случае $access_date разделяется '-'
$date_elements = explode("-",$access_date);
// здесь мы получаем:
// $date_elements[0] = 2007
// $date_elements[1] = 7
// $date_elements[2] = 14
echo mktime(0,0,0,$date_elements[1],$date_elements[2],$date_elements[0]);
?>
Хорошо, а теперь другой вариант. Пусть мы получили строку из MySQL ввиде 2007-07-14 02:40:21. Да, кстати добавим еще и PM для большей сложности. Т. е. имеем: "2007-07-14 02:40:21 PM"
<?php
// наша строка
$date_time_string = '2007-07-14 02:40:21 PM';
// Разделим строку на 3 части - дата, время и AM/PM
$dt_elements = explode(' ',$date_time_string);
// Разделим дату
$date_elements = explode('-',$dt_elements[0]);
// Разделим время
$time_elements = explode(':',$dt_elements[1]);
// Если мы присутвует PM, то мы можем добавить 12 часов к часам и получить 24 часовое время
if ($dt_elements[2]=='PM')
{
$time_elements[0]+=12;
}
// вывод результата
echo mktime($time_elements[0], $time_elements[1], $time_elements[2], $date_elements[1], $date_elements[2], $date_elements[0]);
?>
Опять же часто возникают задачи, когда необходимо знать сколько времени будет через 6 часов, что за день был 35 дней назад или сколько секунд прошло, когда ты в последний раскрывал учебник по математическому анализу. Мы уже знаем как функция mktime() используется для создания timestamp для заданной даты и времени. Сейчас может не слишком наглядно мы проиллюстрируем технику для получение следующей/предыдущей даты или времени.
Как мы знаем mktime() принимает следующие аргументы : часы, минуты, секунды, месяц, день, год. Немного раньше мы рассматривали функцию getdate(), которое возращали все эти данные в удобном для понимания виде.
<?php
// получаем текущий timestamp
$timestamp = time();
echo $timestamp;
echo '</br>';
$date_time_array = getdate($timestamp);
// используем mktime() для создания timestamp
$timestamp = mktime(
$date_time_array['hours'],
$date_time_array['minutes'],
$date_time_array['seconds'],
$date_time_array['mon'],
$date_time_array['mday'],
$date_time_array['year']
);
echo $timestamp;
?>
Для наглядности введем новые переменные:
<?php // получаем текущий timestamp $timestamp = time(); echo $timestamp; echo '</br>'; $date_time_array = getdate($timestamp); $hours = $date_time_array['hours']; $minutes = $date_time_array['minutes']; $seconds = $date_time_array['seconds']; $month = $date_time_array['mon']; $day = $date_time_array['mday']; $year = $date_time_array['year']; // используем mktime() для создания timestamp $timestamp = mktime($hours,$minutes,$seconds,$month,$day,$year); echo $timestamp; ?>
Сейчас после того, как мы получили необходимую информацию в массив и разнесли ее по переменным, код стал легче для чтения и понимания. Очень полезная возможность, которой мы сейчас сможем воспользоваться, - это то, что, если мы захотим добавить каких-нибудь 25 часов к текущей дате, вместо того, чтобы мучаться с mktime(), мы можем просто написать: "$hours +19" и mktime() автоматически прибавит еще один день для нас.
<?php
// получаем текущий timestamp
$timestamp = time();
echo strftime('%H:%M %A %d %b',$timestamp);
echo '</br>';
$date_time_array = getdate($timestamp);
$hours = $date_time_array['hours'];
$minutes = $date_time_array['minutes'];
$seconds = $date_time_array['seconds'];
$month = $date_time_array['mon'];
$day = $date_time_array['mday'];
$year = $date_time_array['year'];
// используем mktime() для создания timestamp
// прибавив 19 часов к $hours
$timestamp = mktime($hours + 19,$minutes,$seconds,$month,$day,$year);
echo strftime('%H:%M %A %d %b',$timestamp);
echo 'время после 19 часов';
?>
Вывод будет примерно таким:
14:58 Суббота 03 Jun 09:58 Воскресенье 04 Jun ~ время после 19 часов
Точно также происходит работа с секундами, минутами, днями или месяцами.
Необходимы минимум и то, с чем чаще всего сталкиваешься, по-моему, я рассказал. В случае если что-либо и упустил, обязательно добавлю. А так в общем-то все
Comments (1) 15.07.2007. 01:36
Ну вот, наличие блога так или иначе обязывает в него что-то писать. Наверное и для этой цели (впрочем также и для цели облегчить себе жить) решил написать немного о простом и понятном - PHP то есть. Для дальнейшего удобства разделив все темы на 2 класса: тривиальные и нетривиальные. Начну с первого:
Большинство уже столкнулись, а те, кто столкнулись, столкнутся обязательно с такой вещью как перенаправление пользователя на другой url. Все, что для этого нужно - это вызвать функцию header(), которая отправляет HTTP-заголовок браузеру. Для того, чтобы браузеру перешел по новому адресу нужно написать следующее:
<?php
header("Location: http://www.php.net");
echo "Test";
?>
Единственным момент, который нужно учесть, - заголовок должен быть отправлен до любой информации, которая будет выведена. В том числе и теги , объявление доктайпа и прочее. Если это не сделать, то вы приблизительно следующую ошибку: "Warning: Cannot modify header information - headers already sent by".
Есть интересный выход избежать появления этой ошибки и в некоторых ситуациях, граничащих с шаманством конечно, его можно также использовать. Выход - использовать буфер вывода. Т.е.:
<?php
ob_start();
echo "Test";
header("Location: http://www.php.net");
ob_flush();
?>
Все. Быстро и понятно. Тема редиректа раскрыта :)
Comments (3) 12.07.2007. 01:07