Pull to refresh

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

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


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



Предметная область
  • Имеется некоторое количество игровых серверов, с которых, через заданный промежуток времени собирается некоторая статистика.
  • Собранная статистика записывается в локальную базу данных, где в одном из столбцов, в формате 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 есть везде.

Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.