Nickolay.info. PHP. Статьи. Хранить ли дату как дату :)

Казалось бы, самый естественный путь для работы с датой и временем на PHP/MySQL - сохранять в базе данных MySQL значение типа "дата и время" - для этого есть тип столбца datetime:

CREATE DATABASE IF NOT EXISTS datetime;
USE datetime;
DROP TABLE IF EXISTS datetime;
CREATE TABLE datetime (
 date datetime
);
INSERT INTO datetime (date) VALUES ( '2011-06-02 18:00:00' );
INSERT INTO datetime (date) VALUES ( '2011-05-03 17:00:00' );

По умолчанию даты хранятся в MySQL в формате год-месяц-день, за это отвечают установки

date_format %Y-%m-%d
datetime_format %Y-%m-%d %H:%i:%s

В типовой ситуации мы хотим выбрать некие записи и вывести их по убыванию (реже возрастанию) даты:

<?php
  $d=mysql_connect('localhost', 'root', 'root')  or die ("Соединение не установлено!");    
  mysql_select_db('datetime',$d);
  $r=mysql_query('select * from datetime order by date desc') or die ("Ошибка запроса!");
  while ($date = mysql_fetch_array($r)) {
   echo '<p>'.$date['date'].'</p>';
  }
?>

Здесь напечатается:

2011-06-02 18:00:00
2011-05-03 17:00:00

То есть, всё верно, но отображение даты неудобно. Можно его преобразовывать функциями PHP date и strtotime перед выводом:

<?php
  $d=mysql_connect('localhost', 'root', 'root')  or die ("Соединение не установлено!");    
  mysql_select_db('datetime',$d);
  $r=mysql_query('select * from datetime order by date desc') or die ("Ошибка запроса!");
  while ($date = mysql_fetch_array($r)) {
   echo '<p>'.date("d.m.Y, H:i",strtotime($date['date'])).'</p>';
  }
?>

Получилось вот что:

02.06.2011, 18:00
03.05.2011, 17:00

- формат даты/времени привычный и сортировка правильная.

Ещё один путь - использовать встроенную прямо в MySQL функцию date_format:

<?php
  $d=mysql_connect('localhost', 'root', 'root') or die ("Соединение не установлено!");
  mysql_select_db('datetime',$d);
  $r=mysql_query('select *,date_format(date,"%Y.%m.%d, %H:%i") as date1 from datetime order by date1 desc') 
   or die ("Ошибка запроса!");
  while ($date = mysql_fetch_array($r)) {
   echo '<p>'.$date['date1'].'</p>';
  }
?>

Этот тест вывел

2011-06-02 18:00:00
2011-05-03 17:00:00

то есть, опять мы получили "день-месяц-год", а замена формата на date_format(date,"%d.%m.%Y, %H:%i"), очевидно, приведёт к неправильной сортировке - 3 мая окажется позже (выше в списке), чем 2 июня!

Чтобы не решать все эти проблемы с форматами, я просто всегда храню дату как длинное целое:

CREATE DATABASE IF NOT EXISTS datetime;
USE datetime;
DROP TABLE IF EXISTS datetime;
CREATE TABLE datetime (
 date bigint default '0'
);
INSERT INTO datetime (date) VALUES ( UNIX_TIMESTAMP('2011-06-02 18:00:00') );
INSERT INTO datetime (date) VALUES ( UNIX_TIMESTAMP('2011-05-03 17:00:00') );

А при выводе форматирую метку времени так, как в данный момент удобно:

<?php
  $d=mysql_connect('localhost', 'root', 'root')  or die ("Соединение не установлено!");    
  mysql_select_db('datetime',$d);
  $r=mysql_query('select * from datetime order by date desc') or die ("Ошибка запроса!");
  while ($date = mysql_fetch_array($r)) {
   echo '<p>'.date("d.m.Y, H:i",$date['date']).'</p>';
  }
?>

Все даты на месте, вывод примера правильный:

02.06.2011, 18:00
03.05.2011, 17:00

Метка времени Unix или timestamp - это число секунд, прошедших от начала так называемой "эпохи Unix" (The Unix Epoch, началась 1 января 1970, 00:00:00 GMT) до текущего времени. Наиболее полезные стандартные функции PHP для работы с датой и временем - date, time, strftime, mktime, естественным образом работают как раз с метками времени Unix.

Сообщение об ошибке date.timezone в PHP последних версий

И ещё одно замечание насчёт вывода дат. PHP последних версий довольно строг в отношении вывода сообщений об ошибках и предупреждений, скорее всего, в Вашем файле настроек стоит

error_reporting = E_ALL & ~E_DEPRECATED

Это, в частности, означает, что вывод предупреждений (Warnings, директива E_WARNING) не подавлен, поэтому при ненастроенном "часовом поясе по умолчанию" каждый вызов функции date(...), в котором не подавлен вывод ошибок (@date(...)), да и другие собщения об ошибках будут сопровождаться предупреждением вида

Warning: Unknown: It is not safe to rely on the system's timezone settings. 
You are *required* to use the date.timezone setting or the 
date_default_timezone_set() function. In case you used any of those methods 
and you are still getting this warning, you most likely misspelled the 
timezone identifier. We selected 'UTC' for '6.0/no DST' instead in 
[ИМЯ_ФАЙЛА] on line [НОМЕР_СТРОКИ]

Просто поставьте в активном файле php.ini настройку date.timezone в секции [DATE], например:

[Date]
date.timezone = "Europe/Moscow"

или просто

[Date]
date.timezone = 6

для часового пояса GMT+6 - если лень искать в списках свой город. - не надо так делать, всё-таки значение зоны из спецификации; а вот без кавычек можно:

[Date]
date.timezone = Europe/Moscow

 Список допустимых временных зон PHP

Узнать, откуда подключён файл настроек php.ini, можно, выполнив это:

<?php phpinfo(); ?>

Ответ содержится в первой таблице в строке Loaded Configuration File

Начиная с PHP 5.1.0 можно установить временную зону по умолчанию для всех функций скрипта и без правки файла php.ini - для этого достаточно вызвать метод date_default_timezone_set с параметром-идентификатором временной зоны (см. ссылку выше).

Например, для Новосибирска делаем так:

date_default_timezone_set ('Asia/Novosibirsk');

Ещё лучше предусмотреть в скрипте соответствующую настройку.

Ещё я делаю так где-нибудь в начале скрипта (лучше всего в коде, выполняющемся 1 раз):

@date_default_timezone_set (date_default_timezone_get()); 
  //Чтоб дальше не ругался предупреждениями на date()

Рейтинг@Mail.ru

вверх гостевая; E-mail