Операции над датами. Использование микросекунд и календарных функций

Наиболее простой способ вычислить период времени между двумя датами в PHP связан с расчетом разности между двумя метками времени Unix. Этот подход использован в сценарии, приведенном ниже.

calc_age.php — сценарий для вычисления возроста по дате рождения

<?php
//Определение даты для расчетов
$day = 11;
$month =5;
$year = 1951;
//Дата рождения требуется в формате день/месяц/год
$bdayunix = mktime (0, 0, 0, $month, $day, $year);
//Получение метки времени Unix для даты рождения
$nowunix = time(); //вычислить метку времени Unix для текущей даты
$ageunix =$nowunix - $bdayunix; //вычислить разность
$age = floor($ageunix/(365*24*60*60)); //преобразование из секунд в годы
echo "Возраст: $age";
?>

В окне веб-браузера это будет выглядеть ТАК.

В этом сценарии дата для подсчета возраста человека была установлена внутри сценария. В реальном приложении эта информация обычно поступает из HTML-формы. Сценарий начинается с вызова функции mktime() с целью вычисления меток времени для даты рождения и текущей даты:

$bdayunix = mktime (0, 0, 0, $month, $day, $year);

$nowunix = time(); //вычислить метку времени Unix для текущей даты

Теперь обе даты имеют одинаковый формат, поэтому можно вычислить их разность:

$ageunix =$nowunix - $bdayunix;

Далее следует более сложный фрагмент кода — обратное преобразование этого перода времени в более естественные единицы измерения. Это уже не метка времени, а возраст человека в секундах. Преобразовать его в годы можно, разделив на количество секунд в году. После этого с помощью функции floor() производится округление в меньшую сторону, поскольку возраст человека составляет, например, 20 лет только по прошествии двадцатого года от рождения:

$age = floor($ageunix/(365*24*60*60));

Все же обратите внимание, что этот подход несколько некорректен, так как он ограничивается диапазоном значений меток времени Unix (nj есть 32-разрядными целыми числами). Пример с днями рождения — совсем не идеальное применение меток времени. Этот пример нормально работает на всех платформах только для тех, кто родился после 1970 года. Windows не может управлять метками времени, относящимися до 1970 года. Кроме того, вычисления не всегда точны, поскольку они не учитывают високосные года и могут дать сбой, если полночь дня рождения попадает на ночь совершения перехода на дневное время.

Операции над датами в MySQL

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

Возможность, которая не сразу возникает как рабочая альтернатива, предусматривает использование MySQL. MySQL представляет широкий спектр функций манипулирования датами, которые нормально работают за пределами ограничений, накладываемых на метки времени Unix. Для выполнения MySQL-запросов вы должны подключиться к серверу MySQL, однако вовсе не обязательно использовать данные исключительно из базы данных.

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

select adddate ('1700-02-28', interval 1 day)

Поскольку 1700год не является високосным, результат выглядит так 1700-03-01 (1 марта 1700года).

Подробное описание синтаксиса для представления и манипулирования датами и временем можно найти в руководстве по MySQL, которое доступно по адресу:

http://www.mysql.com/doc/en/Date_and_time_functions.html

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

mysql_calc_afe.php —использование MySQL для вычисления возраста в годах по дате рождения

<?php
//Определение даты для расчетов
$day = 11;
$month =5;
$year = 1951;
//Преобразование к формату ISO 8601
bdayISO = date("c", mktime(0, 0, 0, $month, $day, $year));
//Использование MySQL-запроса для вычисления возрста в днях
$bd = mysqli_connect('localhost', 'user', 'pass');
$res = mysqli_query($bd, "select datediff(now(), '$bdayISO')");
$age = mysqli_fetch_array($res);
//Преобразование возраста из дней в года (приблизительно)
echo "Возраст: ".floor($age[0]/365.25);
?>

В окне веб-браузера это будет выглядеть ТАК.

После форматирования дня рождения в метку времени ISO серверу MySQL передается следующий запрос:

select datediff(now(), '1951-05-11T00:00:00+03:00')

MySQL-функция now() всегда возвращает текущую дату и время. MySQL-функция datediff() вычитает одну дату из другой и возвращает разницу в днях.

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

Использование микросекунд

В некоторых приложениях измерение времени в секундах не обеспечивает достаточной точности. Если необходимо измерить более короткие периоды, такие как время выполнения PHP сценариев, следует прибегнуть к услугам функции microtime().

Если вы пользуетесь PHP5? вызывайте microtime() со значением true параметра get_as_float. Результатом такого вызова будет метка времени в формате числа с плавающей точкой, с которой можно делать все что угодно. Метка времени будет той же, что возвращается функциями mktime(), time(), date(), однако с дробной частью.

Приведенный ниже оператор

echo number_format (microtime (true), 10, '.' ' ');

выдает что-то наподобие 1080303003.1321949959.

В более старых версиях получать результат в формате числа с плавающей точкой было невозможно. Результат всегда представлялся в виде строки. Вызов microtime() без параметра возвращает строку вида "0.02149300 1080302326". Первое число в этой строке является дробной частью, а второе представляет собой количество полных секунд, прошедших с момента 1 января 1970 года.

Иметь дело с числами, а не со строками, гораздо удобнее, так что если код планируется выполнять только в PHP5, имеет смысл вызывать функцию micritime() всегда с параметром true.

Использование календарных функций

В PHP имеется набор функций, позволяющих выполнять преобразования между различными календарными системами. Наиболее распространенными календарями являются Григорианский, Юлианский и счетчик Юлианских дней.

Григорианский календарь используется в большинстве западных стран. Дата 15 октября 1582 года по Григорианскому календарю эквивалентна дате 5 октябра 1582 года по Юлианскому календарю. До этого момента более распространенным был Юлианский календарь. Разные страны перешли на Григорианский календарь в различное время, некоторые лишь в начале 20 века.

Хотя, возможно, вы слышали об этих двух календарях, скорее всего, вы мало что слышали о счетчике Юлианских дней. Во многом он похож на метки времени Unix. Это счетчик числа дней, начиная примерно с 4000 года до нашей эры. Сам по себе он практически бесполезен, но удобен при преобразованиях из одного формата в другой. Для этого дата сначала преобразуется в значение счетчика Юлианских дней, а затем в требуемый календарный формат.

Для того, чтобы воспользоваться этими функциями в Unix, необходимо скомпилировать календарное расширение вместе с PHP, указав опцию --enable-calendar. Это расширение по умолчанию входит в состав стандартной установки PHP для Windows.

C целью ознакомления рассмотрим прототипы функций, используемых для преобразования из Григорианского календаря в Юлианский:

int gregoriantojd (int month, int day, int year)

string jdtojulian (int julianday)

Для преобразования даты необходимо вызвать обе эти функции:

$jd = gregoriantojd (9,18, 1582);

echo jdtojulian ($jd);

В результате будет выведена юлианская дата в формате MM/ДД/ГГГГ (месяц/день/год).

Существует несколько разновидностей функций для преобразования даты в формат Григорианского, Юлианского, Французского и Еврейского календарей, а также меток времени Unix.




  • Другие |
назадвверхвперед
Rambler's Top100