Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Тексты > Работа с датами различных форматов


Автор: Bikutoru 28.1.2006, 13:46
Работая с PHP, нередко приходится приходится обрабатывать даты различного формата. PHP содержит встроенную функцию date, позволяющую отформатировать метку времени так, как вам хочется, а вот средств для осуществления обратной операции мною замечено не было.

Чтобы было более понятно приведу простой пример. Допустим, нам нужно сделать небольшую админку для регистрации клиентов, в которой нужно указать дату начала и дату окончания действия регистрации и записать всю информацию в базу данных. Вот тут-то мы и сталкиваемся с проблемой разных форматов дат. Не секрет, что для Европы наиболее привычный формат даты - ДД.ММ.ГГГГ, в то время, как для записи даты в MySQL требуется иной формат (например ГГГГ-ММ-ДД). Переформатировать дату - задача несложная. Это можно сделать, например, так:
Код

function reformatDateToMySQLFormat($date) 
{
    if (!preg_match('/^(\d\d)-(\d\d)-(\d{4})$/', $date, $match))
        return false;
    
    return date('Y-m-d', mktime(0, 0, 0, $match[2], $match[1], $match[3]));
}

print reformatDateToMySQLFormat("31-12-2005");

"Так в чем же проблема?" - спросите вы. Проблема в том, что форматы "входных" дат в одном проекте или в разных могут различаться и поэтому приходится писать несколько различных функций, осуществляющих переформатирование дат к единому формату, что, прямо скажем, задача довольно скучная и рутинная. Поэтому я предлагаю средство, которое позволяет переформатировать даты из
любого формата в любой.
Примечание: конечно же, дату можно получать извне по принципу "один компонент - одно поле ввода", но "склеивание" компонентов при таком варианте, на мой взгляд, тоже нельзя назвать творческой работой.

Итак класс DateFormatter.
Для создания его экземпляра следует воспользоваться конструктором, принимающим на вход один аргумент - формат даты. Каждый компонент даты именуется буквой латинского алфавита:
y для года;
m для месяца;
d для дня;
h для часа;
i для минуты;
s для секунды.
Как видите, изобретать велосипед я не стал и воспользовал мнемоники из стандартной функции date. Формат даты - это строка, представляющая собой шаблон даты. Например форматы "dd.mm.yyyy" и "yyyy-mm-dd" соответствуют двум форматам
приведенным ранее (ДД.ММ.ГГГГ и ГГГГ-ММ-ДД, соответственно).

После задания шаблона, экземпляр класса DateFormatter становится способным "понимать" даты указанного формата. Небольшой примерчик:
Код

require_once "DateFormatter.php";

$df =& new DateFormatter("dd.mm.yyyy hh:ii:ss");
$time = $df->getTimestamp("28.01.2006 12:35:00");
if ($time != -1) {
    print date("Y-m-d H:i:s", $time) . "<br>\n";
}

Основные методы класса DateFormatter? используемые для получения времени и его компонентов:
getTimestamp($dateString) - возвращает метку времени, соответствующую дате, заданной в $dateString;
getYear($dateString) - возвращает значение года даты, заданной в $dateString;
getMonth($dateString) - возвращает значение месяца даты, заданной в $dateString;
getDay($dateString) - возвращает значение дня даты, заданной в $dateString;
getHours($dateString) - возвращает значение часа даты, заданной в $dateString;
getMinutes($dateString) - возвращает значение минут даты, заданной в $dateString;
getSeconds($dateString) - возвращает значение секунд даты, заданной в $dateString.

В принципе, на этом можно и остановиться, но мне показалаось, что это решение можно улучшить. Посмотрите на пример кода, приведенный чуть ранее. Перевод даты из одного формата в другой требует от пользователя, чтобы он узнавал метку времени и передавал ее в функцию date. Мне показалось, что это не совсем правильно, именно поэтому я реализовал еще две функции:
format($time) - возвращает отформатированную в соответствии с заданным форматом дату, заданную меткой времени $time;reformatTo($dateString, $newFormatter) - возвращает отформатированную в соответствии с форматом, указанным в $newFormatter, дату, заданную строкой $dateString.

C учетом этих двух функций переформатирование даты из одного формата в другой будет иметь следующий вид:
Код

require_once "DateFormatter.php";

$df   =& new DateFormatter("dd.mm.yyyy hh:ii:ss");
$ndf =& new DateFormatter("dd/mm/yy hh:ii:ss");

print $df->reformatTo("31.12.2005 23:59:59", $ndf);

Не знаю как вам, но мне такое решение определенно нравится больше.

Ну вот и все, свое решение я описал, как мне кажется, довольно подробно. Если кому-то оно пригодится, буду только рад. Если есть какие-нибудь вопросы или предложения, высказывайте.

Автор: Mal Hack 28.1.2006, 14:15
Цитата
array strptime ( string timestamp, string format )


Универсального решения конечно нет, но все же..
Плюс, обычно в своих системах разрабочики используют 1-2 формата дат, для переформирования которых уже есть свои заготовки.

В догонку: http://vingrad.ru/PHP-SRC-002931

Автор: Bikutoru 28.1.2006, 17:44
strptime это хорошая функция, но у нее как минимум один недостаток
Цитата(http://ru.php.net/manual/en/function.strptime.php)

PHP 5 >= 5.1.0RC1

А ведь кое-кто еще работает с четверкой (я например).

Цитата(Mal Hack @ 28.1.2006, 15:15 Найти цитируемый пост)

в своих системах разрабочики используют 1-2 формата дат, для переформирования которых уже есть свои заготовки

Согласен, но у меня бывали случаи, когда клиенты говорят что-то вроде "А нельзя kb на этой странице сделать, чтобы время показывалось как ...". Переписывать имеющуюся функцию переформатирования нельзя, т.к. она может использоваться и в других местах, поэтому приходится писать новую методом "copy&paste". А с помощью моего класса мы просто исправляем с скрипте строку формата, использующуюся при создании экземпляра класса, и все готово smile

Автор: IZ@TOP 28.1.2006, 23:02
Цитата(Bikutoru @ 28.1.2006, 18:44 Найти цитируемый пост)

strptime это хорошая функция, но у нее как минимум один недостаток

Хэй... а как же эта http://ru.php.net/manual/ru/function.strtotime.php ???

Автор: Bikutoru 31.1.2006, 17:25
IZ@TOP, позволь отвечу несколькими строчками кода:
Код

<?php

print date('Y-m-d', strtotime('31.01.2006'));
//Получаем warning

require_once 'DateFormatter.php';
$df =& new DateFormatter("dd.mm.yyyy");
print date('Y-m-d', $df->getTimestamp('31.01.2006'));
// Получаем 2006-01-31

?>

Добавлено @ 17:29
Кстати, если кому-нибудь интересно, я заменил файл на чуть-чуть исправленную версию.

Автор: Ciber SLasH 31.1.2006, 21:06
strtotime принимает строку с http://www.gnu.org/software/tar/manual/html_chapter/tar_7.html форматом даты.
Т.е. нуно так: strtotime('31/01/2006')

Автор: Bikutoru 1.2.2006, 11:08
Ciber SLasH, а ты первый пост читал? Мой класс для того и нужен, чтобы разный формат дат можно было обрабатывать...
Добавлено @ 11:10
...что и демонстрируется тем фрагментом кода.

Автор: Alone 2.3.2006, 11:09
Мои 5 копеек:

Для хранения даты в ЛЮБОЙ БД используем поле Integer и храним там дату в виде unix timestamp.
Из таймстампа в пхп можно привести К ЛЮБОМУ НУЖНОМУ ВАМ ВИДУ с помощью date("<format string>", $tstamp).

А вот для реверса из строки в исходный интегер - этот класс как раз и может быть полезен.

Автор: CyClon 3.3.2006, 14:53
Alone, Про unix timestamp по подробнее можно? Помоему это дана формата:

Цитата
01.01.2005 00:00:00


Или я не прав?

Автор: AztEK 3.3.2006, 19:18
Нет, не прав.
Это формат вида 1336172882

Автор: CyClon 3.3.2006, 21:33
AztEK, И что это обохначает? Может подкинешь ссылку, где можно почитать? У меня вечный вопрос с хранением даны, сейчас как ламер храню в varchar(20) такого типа dd.mm.yy | hh:ii

Автор: AztEK 4.3.2006, 19:51
CyClon это количество секунд, прошедших с начала эпохи UNIX (1 января 1970 года 05:00:00)

Автор: CyClon 4.3.2006, 21:58
AztEK, В MySQL есть такое поле timestamp, но читал в статье, тчо лучше хранить в varchar... Как объясните?

Автор: Ciber SLasH 5.3.2006, 04:03
2CyClon:
Скачай мануал на русском на php.net и поиск по функции time.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)