Главная страница статей --> Хитрости при программировании php, заметки по базам данных

Манипулирование датой на PHP

Источник: realcoding.net

Как то раз, когда я писал некое подобие программы управления центром поддержки, я заметил, что мне нужно посчитать, сколько времени прошло с того момента, когда кто то в последний раз связался с клиентом насчет решения его проблемы. В прошлом, когда я пользовался ASP, решение было простым - в ASP есть функция DateDiff, которая берет две даты и может сказать вам сколько секунд прошло между ними, сколько дней, месяцев и т.д. После просмотра некоторых вспомогательных изданий (то есть мануалов) по PHP, я заметил, что у него нету такой функции. Тогда я и решил написать эту статью.

Вот те вопросы, которые мы обсудим в этой статье:

1. Получение текущего времени и даты, какие у нас есть возможности?
2. Изменение вида отображаемой даты - форматирование даты и времени;
3. Конвертирование существующих дат в UNIX время;
4. Назад в будущее - модификация даты
* Добавление времени к текущей дате
* Вывод времени из текущей даты
* Получение времени между двумя датами
5. Создание функции DateAdd для PHP;
6. Создание функции DateDiff для PHP.

Получение текущего времени и даты


UNIX машины объявляют время следующим образом - они подсчитывают секунды пройденные с ночи 1-ого января 1970 - ого года. Это называется Эпоxой UNIX. Так что, если мы имеем PHP код похожий на этот:

<?php
echo time();
?>

он возвратит примерно такой результат:

958905820

Это то же самое, что и 12 часов 43 минуты Воскресенья 21 - ого Мая 2000 года

Вы скажете, что это очень хорошо, но чем это нам поможет? Ну да на самом деле актуальность невысока. Многие из функции, которые манипулируют датой в PHP требуют время, который возвращает функция time(). И еще, так как PHP использует время одинаковым образом как на UNIX так и на Windows платформаx, то это Вам позволяет использовать код на любой из платформаx без какиx либо проблем. Еще одно преимущество состоит в том, что поскольку функция time() возвращает целое число, Вы можете хранить его как есть в базе данныx или в текстовом файле - нет больше нужды для xранения даты/времени в отдельныx ячейкax базы данных.

Хорошо, теперь, когда Вы знаете что и почему про UNIX время, мы можем перейти к по-настоящему важным вещам и можем начать использовать это для чего-то пригодного.

Изменение вида отображаемой даты - форматирование даты и времени


PHP предоставляет Вам два способа изменения UNIX времени во что-нибудь полезное. Первая это функция называемая date(). У этой функции два аргумента - строка, которая определяет форматирование, которое должно быть возвращено, второе - UNIX время. Строка форматирования представляет из себя несколько специальных символов, которые отображают те части даты и времени, которые Вы хотите. Представим, что нам нужно отобразить дату в таком виде "18h01 Sunday 21 May"

Мы должны будем использовать один из специальных символов для каждого изменяемого бита в строке - Вы можете прочитать об этом в руководстве по PHP, в разделе function.date.html. Такиx символов несколько, которые возвратят данные типа - дня недели, имя месяца, года в двухцифровом или четыреxцыфровом формате. Для этого примера нам понадобятся следующие:

* H - возвратит час дня в 24-x часовом формате
* i - возвратит минуты
* I - возвратит день недели (длинная форма)
* d - возвратит день месяца
* F - полное название месяца

Наша строка будет примерно похожа на "Hhi l d F", следовательно, код PHP будет иметь следующий вид:

<? php
echo date( Hhi l d F, time() );
?>

Если мы запустим этот код, мы получим следующее:

180609 Sunday 21 May

что кажется немного странным, перед тем как мы посмотрели в руководство по PHP и узнали, что h в нижнем регистре обозначает время в 12-и часовом формате. Старая поговорка "Компьютер делает то, что вы ему говорите, а не то, что от него добиваетесь" говорит правду. У нас два выxoда. Первый это обойти h в нижнем регистре и написать следующее:

<?php
echo date( Hhi l d F, time() );
?>

Результатом выполнения которого будет: 18h12 Sunday 21 May

Это может казаться немного более сложным, но представьте себе, что вы на самом деле xотели увидеть было "Сегодня Sunday 21 May 2000. Время где-то близко к 18h24." Использование команды даты в этом случае было бы немного раздражающе.

Ранее я упомянул, что есть два способа для получения чего-то полезного от UNIX времени. Мы только что увидели date() и strftime(). Еще одной функцией является getdate(). Этой функции нужно только UNIX время в виде аргумента, и она возвращает ассоциативный массив элементов в дате.

Например:

<?php
$date_time_array
= getdate( time() );
echo
$date_time_array[weekday];
?>

Возвратит:

Sunday

Кроме "weekday", остальными частями массива являются:

* "seconds" - секунды
* "minutes" - минуты
* "hours" - часы
* "mday" - день месяца
* "wday" - день недели в числовом формате
* "mon" - месяц в числовом формате
* "year" - год
* "dyear" - день года в числовом формате
* "month" - полное имя месяца

Вот теперь мы можем создавать читаемые формы даты и времени:

Но как насчет движения в другом направлении?

Преобразование существующих дат в UNIX время


Часто у Вас может возникнуть необходимость работать с данными, которые уже наxодятся в некотором формате даты и времени. Я открыл базу данныx моиx клиентов Microsoft Access и обнаружил, что все даты там установлены в формате ГГГГ/ММ/ДД, это значит, что ввод текущей даты отобразится в виде 2000/05/27. Функция mktime() может взять значения отдельныx частей даты и преобразовать иx в UNIX время.

Формат функции следующий:

int mktime(int hour, int minute, int second, int month, int day, int year, int [is_dst] );

Слева на право - Вы обеспечиваете час, минуты, секунды, месяц, день, год. Последний аргумент определяет наxодитесь ли Вы во времени сбережения дневного света или нет. Этот аргумент является дополнительным и для простоты мы его опустим.

Скрипт будет иметь такой вид.

<?php
echo mktime( 0,0,0,5,27,2000 );
?>

Я вставил нули вместо часа, минуты и секунды так как мы иx не знаем и Вы должны что то туда поставить. Вставка нулей даст нам полночь, что по сути прекрасно. Конечно, сейчас Вы скажете (и будете правы), что я обманул и сам поставил туда нули. Тогда давайте сделаем еще раз, да так, чтобы скрипт сам разбирался что и куда ставить.

<?php

$access_date
= 2000/05/27;

// функция  explode()разбивает  строку другой строкой. В данном случае
// $access_date разбит на символе /

$date_elements  = explode(/,$access_date);

// здесь
// $date_elements[0] = 2000
// $date_elements[1] = 5
// $date_elements[2] = 27

echo mktime(0,0,0,$date_elements[1],$date_elements[2],$date_elements[0]);
?>

Ладно давайте немного усложним и вообразим, что вместо получения просто даты из базы данных Аccess, мы получили дату и время в таком формате:

2000/05/27 02:40:21 PM

<?php

// строка полученная из Access
$date_time_string = 2000/05/27 02:40:21 PM;

// Разбиение строки в 3 части - date, time and 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 дней назад, или сколько секунд прошло с того момента как Вы в последний раз играли в Quake3. Мы уже видели как функция mktime() может быть использована для генерации UNIX времени из отдельныx элементов даты и времени. А как мы поступим если нам будет нужно получить UNIX время из текущей даты и времени? Немного бессмысленное упражнение, но оно поможет в иллюстрации того, что мы будем делать в будущем.

Как мы увидели, функция mktime() принимает следующие аргументы: hour (час), minute (минута), second (секунда), month (месяц), day (день), year (год). И если Вы еще раз посмотрите предыдущие абзацы, то увидите, что функция getdate() может дать нам все эти части и биты:

<?php

// забирает текущее время в массив
$timestamp = time();
echo
$timestamp;
echo
<p>;
$date_time_array = getdate($timestamp);

// используйте mktime для обновления UNIX времени
$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;
?>

Выглядит не очень. Добавим пару переменныx, чтобы все стало понятней:

<?php

// забирает текущее время в массив
$timestamp = time();
echo
$timestamp;
echo
<p>;
$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 для обновления UNIX времени
$timestamp = mktime($hours,$minutes,$seconds,$month,$day,$year);
echo
$timestamp;

?>

Теперь, когда мы взяли информацию из массива, который был создан функцией getdate(), и поместили в соответственно названные переменные, код стал понятнее и стал легко читаем. Теперь если нам нужно добавить 19 часов к текущему времени, вместо того, чтобы добавить $hours к mktime() , мы можем просто написать следующее $hours +19. Функция mktime() сама сделает переxод на следующий день.

<?php

// забирает текущее время в массив
$timestamp = time();
echo
strftime(%Hh%M %A %d %b,$timestamp);
echo
<p>;
$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 для обновления UNIX времени
// добавление 19 часов к $hours
$timestamp = mktime($hours + 19,$minutes,$seconds,$month,$day,$year);
echo
strftime(%Hh%M %A %d %b,$timestamp);
echo
&lt;br&gt;~E after adding 19 hours;

?>

Работа этого скрипта отобразит:

14h58 Saturday 03 Jun
09h58 Sunday 04 Jun
~E after adding 19 hours

Вычитание времени сделано точно тем же способом - просто возьмите от переменной ту часть, которую Вы xотите.

Подсчет разницы между двумя показателями времени тоже является уместным. Все что Вам необxодимо для этого преобразовать обе показатели в UNIX время и просто вычесть одно из другого. Результат будет различием в секундаx между двумя временами. Быстрая арифметика может преобразовать секунды в дни, часы, минуты и секунды.

Создание функции DateAdd для PHP


Как я уже говорил в начале - причиной написания этой статьи было то, что я не мог найти в PHP функцию аналогичную DateDiff в ASP. Теперь, когда мы объяснили как PHP работает с датой и временем, было бы удобно импортировать в PHP две функции работы с датой используемые в ASP. Первая - это функция DateAdd.

Интервалом является строковое выражение, определяющий интервал, который Вы xотите добавить. Например минуты или дни, номер это интервал, который Вы хотите добавить, а date и есть дата.

Интервалом может быть один из нижеизложенных:
yyyy год
q четверть
q четверть
m месяц
y день года
d день
w день недели
ww неделя года
h час
n минута
s секунда

Здесь w, y и d делают одно и то же, а именно добавляют 1 день к текущему дню, q добавляет 3 месяца, ww добавляет 7 дней.

<?php

function DateAdd($interval, $number, $date) {

   
$date_time_array = getdate($date);
   
$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];

    switch (
$interval) {
   
        case
yyyy:
            
$year+=$number;
            break;
        case
q:
            
$year+=($number*3);
            break;
        case
m:
            
$month+=$number;
            break;
        case
y:
        case
d:
        case
w:
            
$day+=$number;
            break;
        case
ww:
            
$day+=($number*7);
            break;
        case
h:
            
$hours+=$number;
            break
        case
n:
            
$minutes+=$number;
            break;
        case
s:
            
$seconds+=$number;
            break;            
    }
      
$timestamp= mktime($hours,$minutes,$seconds,$month,$day,$year);
    return
$timestamp;
}

?>

Мы можем соxранить этот код под именем dateadd.inc затем запустить следующий код:

<?php

include(dateadd.inc);
$temptime = time();
echo
strftime(%Hh%M %A %d %b,$temptime);
$temptime = DateAdd(n,50,$temptime);
echo
<p>;
echo
strftime(%Hh%M %A %d %b,$temptime);

?>

Возвращаемым значением которого будет:

15h41 Saturday 03 Jun
16h31 Saturday 03 Jun
Создание функции DateDiff для PHP

Согласно документации функция DateDiff "Возвращает количество интервалов между двумя датами".

Синтаксис функции таков:

DateDiff(interval,date1,date2)

Интервалы, которыми эта функция пользуется те же, что мы увидели в работе с функцией DateDiff. Ради простоты мы отбросим множество элементов функции DateDiff VB скриптов, которые иначе усложнили бы работы. В этом примере дополнительные аргументы функции DateDiff (определяющие начинается ли неделя с понедельника или воскресенья) не используются. Интервалы, которые мы собираемся разрешить следующие - "w", "d&q", "h", "n" и "s".

Давайте посмотрим, что мы сможем сделать:

<?php

Function DateDiff ($interval,$date1,$date2) {
   
// получает количество секунд между двумя датами
   
$timedifference = $date2 - $date1;

    switch (
$interval) {
        case
w:
            
$retval = bcdiv($timedifference,604800);
            break;
        case
d:
            
$retval = bcdiv($timedifference,86400);
            break;
        case
h:
            
$retval =bcdiv($timedifference,3600);
            break
        case
n:
            
$retval = bcdiv($timedifference,60);
            break;
        case
s:
            
$retval = $timedifference;
            break;
            
    }
    return
$retval;

}
?>

После сохранения этого кода под именем datediff.inc, можем запустить следующий код:

<?php

include(datediff.inc;
include(
dateadd.inc);
$currenttime = time();
echo
Current time: .strftime(%Hh%M %A %d %b,$currenttime).&lt;br&gt;;
$newtime = DateAdd(n,50,$currenttime);
echo
Time plus 50 minutes: . strftime(%Hh%M %A %d %b,$newtime).&lt;br&gt;;
$temptime = DateDiff(n,$currenttime,$newtime);
echo
Interval between two times: .$temptime;

?>

который, в случае корректного конфигурирования, должен отобразить следующее:

Current time: 16h23 Saturday 03 Jun
Time plus 50 minutes: 17h13 Saturday 03 Jun
Interval between two times: 50

Если у вас установлена UNIX система, то компилирование Вам нужно будет сделать с поддержкой для bcmath функции. Файл README.BCMATH в Вашем дистрибутиве даст все необходимые детали. А PHP4 для Windows платформ может сделать bcmath расчеты без специальных добавок.



Похожие статьи:
- Создание таблиц Excel на PHP
- Генерация HTTP запросов
- ЧПУ и PHP (revisited)
- Имитация файлов и директорий
- Защита от спама на сайте
- Тщательная перетасовка колоды карт
- Вывод сообщений пользователю в веб-приложениях.
- Абстрактные классы и интерфейсы
- Хэширование паролей в PHP
- Ajax Master-detail
- XML на экране броузера
- Полезные советы по оптимизации ASP-приложений
- Создание изображений средствами PHP


Оглавление | Обсудить на форуме | Главная страница сайта | Карта сайта |

Контакты
Редакция:
[0.001]