Как стать автором
Обновить

Определение временного промежутка между двумя датами

Время от времени приходится вести отсчет от или до какой-нибудь даты. Например, сколько времени осталось до празднования Нового Года или до зарплаты, что более актуально. Как высчитать нужный нам временной промежуток между двумя датами — текущей и прошедшей/будущей? Задача, на самом деле, очень простая, но почему-то нередко вызывает трудности. Почему? Не знаю… давайте уже делом займемся.


Решим задачу на «живом» примере. Не так давно как раз реализовывал описанный ниже алгоритм.



Предметная область
  • Имеется некоторое количество игровых серверов, с которых, через заданный промежуток времени собирается некоторая статистика.
  • Собранная статистика записывается в локальную базу данных, где в одном из столбцов, в формате Unix timestemp, хранится время последнего обновления.
  • Для пользователя, на основе данных из БД, формируется таблица со статистикой, в том числе выводится время последнего обновления, дабы пользователь мог оценить актуальность данных.

Задача не подразумевает под собой ничего особенного. В принципе, так как дата хранится в формате Unix timestamp, то с помощью функции date() ее можно вывести в любом удобном нам представлении. Но, если учесть, что данные обновляются исключительно часто, допустим, раз в минуту, то выводить время обновления в привычном виде крайне неудобно. Мы будем заставлять пользователя смотреть на часы и самостоятельно определять сколько времени прошло с момента обновления информации. Согласитесь, гораздо более дружелюбно смотрелась бы фраза «обновлено 2 минуты назад» и ничего считать не нужно. Поэтому, задачу вычисления прошедшего промежутка времени лучше возложить на скрипт, чем мы сейчас и займемся.


Сразу приведу код, чтобы не мучать особенно нетерпеливых.


/**
* Высчитываем разницу между двумя датами
*
* @param integer $cur_time
* @param integer $time
* @return array
*/
function getTimeDifference($cur_time, $time) {
if ($time > $cur_time) {
$difference = $time - $cur_time;
} elseif ($time < $cur_time) {
$difference = $cur_time - $time;
} else {
return array('days' => 0, 'hours' => 0, 'mins' => 0);
}

$diff_days = floor($difference / 84600);
$diff_hours = floor($difference / 3600);
$diff_minutes = floor($difference / 60);
$return = array();
$return['days'] = $diff_days;
// Если разница > суток - 1 час
if ($diff_hours > 23) {
$return['hours'] = $diff_hours - (24 * $diff_days);
} else {
$return['hours'] = $diff_hours;
}
// Если разница > часа - 1 минута
if ($diff_minutes > 59) {
$return['mins'] = $diff_minutes - (60 * $diff_hours);
} else {
$return['mins'] = $diff_minutes;
}
return $return;
}

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


Функция принимает 2 параметра — две временных точки, между которыми будет найден интервал. По идее, параметр $cur_time содержит текущее время, хотя, по факту, может быть любым timestamp'ом. $time — timestamp прошедшего или будущего времени.


$diff_days = floor($difference / 84600);
$diff_hours = floor($difference / 3600);
$diff_minutes = floor($difference / 60);

Пожалуй ключевой, хотя и самый просто момент. Высчитываем сколько дней, часов и минут соответственно входит в получившийся временно промежуток. Суть идеи проста. Мы знаем, что в одной минуте 60 секунд. В одном часе их 3600 = 60 секунд * 60 минут. В сутках 86400 секунд = 60 секунд * 60 минут * 24 часа.


Для округления используем floor(), потому как нам нужно только кол-во полных прошедших дней и часов. Остатки выразим в часах и минутах соответственно.


Значение $diff_days отражает реальное количество дней, потому можем смело возвращать их из функции. А вот количество часов может превышать 23, потому как временной промежуток между датами может быть более суток или даже более месяца. Следовательно, нам нужно отсечь лишние часы, которые и так нашли свое отражение в количестве дней. Аналогично с минутами.


// Если разница > суток - 1 час
if ($diff_hours > 23) {
$return['hours'] = $diff_hours - (24 * $diff_days);
} else {
$return['hours'] = $diff_hours;
}

Делаем проверку на то, что кол-во получившихся часов не превышает 23. Если нет, то добавляем значение в массив, который вернем из функции. Если превышает, то вычитаем из него количество дней, помноженное на 24 (кол-во часов в сутках :)). Получившийся результат не что иное, как чистое кол-во часов.


Тоже самое проделываем с минутами.


Вуаля! Хвалим себя любимых. Получили, что хотели. Теперь вызываем функцио и смотрим результат ее работы:


print_r(getTimeDifference(1242902278, 1242803038));

Результата работы:


Array
(
[days] => 1
[hours] => 3
[mins] => 34
)

Надеюсь, разжевал код настолько, что будет понятно даже тем, кто видит PHP впервые :) Кстати, если заметили, то алгоритм не использует, да и не может, каких-либо специфических возможностей языка, потому легко может быть перенесен на любой другой. Благо, Unix timestemp есть везде.

Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.