Работа с датами и временем.

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

Представление времени в формате timestamp:

 
                       int time()

возвращает время в секундах, прошедшее с полуночи 1 января 1970 года по Гринвичу. Этот формат данных принят в Unix как стандартный. Время последнего изменения файлов указывается в таком формате. Все функции по работе со временем имеют представление, которое называется unix timestamp(). Функция timestamp() не отражает реальное ( астрономическое) число секунд с 1 января 1970 года, а немного отличается от него. Впрочем, это нисколько не умаляет преимущества от его использования:

 
                       mixed microtime(bool $asFloat=false)

Если параметр $asFloat не задан, возвращает строку в формате: "дробная_часть целая_часть", где целая_часть — результат, возвращаемый функцией time(), а дробная_часть — дробная часть секунд, служащая для более точного измерения промежутков времени. В качестве разделителя в строке используется единственный пробел. Для того чтобы работать со временем, необходимо разбить возвращенное значение по этому пробелу, а затем просуммировать полученные части:

 
                       list ($frac, $sec)=explode(" ", microtime());
                       $time = $frac + $sec;

Специально для того, чтобы каждый раз не выполнять эти команды, в РНР-5 добавился необязательный параметр — $asFloat. Если его значение равно true, функция сразу же возвращает вещественное число. Параметр $asFloat не поддерживается в РНР-4.

Вычисление времени работы скрипта. Функцию microtime() удобно использовать для измерения времени работы скрипта. В самом деле, запишите первой командой сценария:

 
                       define("START_TIME", microtime(true)); 
                         // тут тело программы
                         // должно находиться.  
                       printf("Время работы скрипта: %.5f с", microtime(true)-START_TIME);

Вся основная работа программы должна заключаться между этими двумя вызовами — тогда время будет выводиться с высокой достоверностью. Данный способ выводит не процессорное ("чистое") время, а "абсолютное". Если сервер хостера в момент запуска сценария окажется сильно загруженным другими программами, время возрастет. Вместе с тем, ограничения, которые выставляют все хостинг-провайдеры ( например, 30 секунд), касаются "чистого" процессорного времени, а оно никак не зависит от загруженности процессоров. Выполнив в скрипте команду sleep(1ооооо), Вы заставите его "заснуть" на сто тысяч секунд. Так как при этом он не будет потреблять ресурсов, ограничения хостера на него не повлияют.

Большие вещественные числа. Некоторые фокусы с функцией timestamp():

 
                      < ?php 
                      ## Использование microtime(). 
                      $time = microtime(true);
                      printf("с полуночи 1 января 1970: %f секунд.< br>", $time);
                      echo "с полуночи 1 января 1970: $time секунд.< br>"; 
                      ? >

Запускаем скрипт и Вы видите, что числа, выведенные в браузер немного различаются.

с полуночи 1 января 1970: 1555814304.038956 секунд.
с полуночи 1 января 1970: 1555814304.039 секунд.

Функции printf() и sprintf() округляют дробные числа не так, как это происходит при "разворачивании" переменной в строке. Разница заметна потому, что в $time содержится очень большая величина — сотни миллионов. В машинной арифметике все числа хранятся приближенно - числа идут с некоторой очень маленьким шагом, и чем больше число, тем меньшая у него точность.

В переменной $time время хранится с достаточной степенью точности, так что можете выполнять с ним арифметические действия без всяких опасений на погрешность. Но будьте осторожны при выводе результата: он может сильно отличаться от реального значения переменной.

Построение строкового представления даты:

 
                      string date(string % format [,int $timestamp])

Функция string date(string % format [,int $timestamp]) возвращает строку, отформатированную в соответствии с параметром $format и сформированную на основе параметра $timestamp. Если последний не задан — то на основе текущей даты. Строка формата может содержать обычный текст, перемежаемый одним или несколькими символами форматирования:

-и — количество секунд, прошедших с полуночи 1 января 1970 года;

-z — номер дня от начала года;

-Y — год, 4 цифры;

-у — год, 2 цифры;

-F — название месяца, например, January;

-m — номер месяца;

-M — название месяца, трехсимвольная аббревиатура, например, Jan;

-d — номер дня в месяце, всегда 2 цифры (первая может быть 0);

-j — номер дня в месяце без предваряющего нуля;

-w — день недели, 0 соответствует воскресенью, 1 — понедельнику, и т. д.;

-1 — день недели, текстовое полное название, например, Friday;

-D — день недели, английское трехсимвольное сокращение, например, Fri;

-а — am или рm;

-А — AM или РМ;

-h — часы, 12-часовой формат;

-H — часы, 24-часовой формат;

-i — минуты;

-s — секунды;

-S — английский числовой суффикс (nd, th и т.д.);

Те символы, которые не были распознаны как форматирующие, подставляются в результирующую строку "как есть". Не злоупотребляйте этим, поскольку довольно мало английских слов не содержат ни одной из перечисленных выше букв. Набор символов форматирования многочислен. Вот, пример использования функции date():

 
                      < ?php 
                      ## Вывод дат.
                      echo date ("d F Y h:i:s a")."< br>"; 
                      echo date ("Сегодня d.m.Y")."< br>";
                      echo date ("Этот файл датирован d.m.Y", filectime (__FILE__ ));
                      ? >

21 April 2019 05:38:24 am
Сегодня 21.04.2019
Этот файл датирован 11.11.2018

 
                      string strftime(string $ format [,int $ timestamp])

Функция, предназначенная для получения текстового представления даты по значению $timestamp ( если этот параметр опущен, то в качестве него берется текущее время). В отличие от функции date(), названия месяцев и дней недели, которые она формирует, существенно зависят от текущей выбранной локали - функции setlocale().

Строка $format, передаваемая этой функции, может содержать текст и спецификаторы форматирования. В отличие от функции date(), последние задаются в виде %X, где X— одна из букв английского алфавита. Вот некоторые наиболее популярные спецификаторы форматирования:

-%Y — год (например, 2004);

-%у — краткое представление года (например, 04);

-%m — номер месяца (от 01 до 12);

-%d — число (в диапазоне от 01 до 31);

-%H — часы (от 00 до 23);

-%M — минуты (от 00 до 59);

-%S — секунды (от 00 до 59);

-%B — полное название месяца в соответствии с текущей локалью (например, "Март");

-%b — сокращенное название месяца (например, "мар");

-%d — сокращенное название дня недели (например, "Пн");

-%c - некоторые текстовые представления даты, определяемое текущей локалью.

Полный список спецификаторов форматирования можно найти в описании функции strftime() из документации РНР.

 
                       < ?php 
                       ## Использование strftime().
                          // Активизируется текущую локаль (иначе дата будет на английском).
                       setlocale(LC_ALL, " );
                          // Выводится 2 предложения.
                       echo strftime("%B %Y года, %d число. Был %А, часы показывали %Н:%М.");
                       ? >

April 2019 года, 21 число. Был %А, часы показывали %Н:%М.

Если пропустите вызов setlocale(), функция strftime() вернет текст с английскими вариантами названий.

Построение timestamp:

 
                      int mktime([int $houx] [,int $minute] [,int $second] 
                                    [,int $month] [,int $day] [, int $year])

Существует функция, которая проводит обратное преобразование — mktime(). Все параметры функции mktime() необязательны, но пропускать их можно, конечно же, только справа налево. Если какие-то параметры не заданы, на их место подставляются значения, соответствующие текущей дате. Функция возвращает значение в формате timestamp(), соответствующее указанной дате. Правильность даты, переданной в параметрах, не проверяется. В случае некорректной даты ничего особенного не происходит — функция "делает вид", что это ее не касается, и формирует соответствующий формат timestamp(). Для иллюстрации рассмотрим три вызова ( два из них — с ошибочной датой), которые тем не менее возвращают один и тот же результат:

                       echo date ("M-d-Y", mktime (0,0,0,1,1,2005)); 
                              // правильная дата 
                       echo date ("M-d-Y", mktime(0,0,0,12,32,2004));
                              // неправильная дата 
                       echo date ("M-d-Y", mktime(0,0,0,13,1,2004)); 
                              // неправильная дата

Легко убедиться, что выводятся три одинаковых даты:

Jan-01-2005Jan-01-2005Jan-01-2005

 
                       int strtotime(string $time [,int $timestamp])

При вызове функции mktime() легко перепутать порядок следования параметров и получить неверный результат. Функция strtotime() лишена этого недостатка. Она принимает строковое представление даты в свободном формате и возвращает соответствующий формат timestamp().

Функция strtotime() воспринимает строковые представления некоторых дат. Результат выводится в виде таблицы, в которой отображается timestamp(), заново построенное timestamp-формату строковое представление даты:

                       < ?php 
                       ## Использование функции strtotime()
                       $check = array( "now", 
                       "10 September 2000", 
                       "+1 day", 
                       "+1 week",
                       "+1 week 2 days 4 hours 2 seconds", 
                       "next Thursday", "last Monday",
                       );
                       ? >
                       < table width="90%"> 
                       < tr align="center">
                       < th>Входная строка< /th> 
                       < th>Timestamp< /th> 
                       < th>Получившаяся дата< /th>
                       < th>Сегодня< /th>
                       < /tr>
                       < ?foreach ($check as $str) {? > 
                        < tr>
                          < td>< ?=$str? >< /td>
                          < td>< ?=$stamp=strtotime($str)? >< /td> 
                          < td>< ?=date("Y-m-d H:i:s", $stamp)? >< /td>
                          < td>< ?=date("Y-m-d H:i:s", time())? >< /td>
                        < /tr> 
                        < ?}? >
                        < /table>

Вот и результат работы данного скрипта:

Входная строка Timestamp Получившаяся дата Сегодня
now 1555814304 2019-04-21 05:38:24 2019-04-21 05:38:24
10 September 2000 968529600 2000-09-10 00:00:00 2019-04-21 05:38:24
+1 day 1555900704 2019-04-22 05:38:24 2019-04-21 05:38:24
+1 week 1556419104 2019-04-28 05:38:24 2019-04-21 05:38:24
+1 week 2 days 4 hours 2 seconds 1556606306 2019-04-30 09:38:26 2019-04-21 05:38:24
next Thursday 1556139600 2019-04-25 00:00:00 2019-04-21 05:38:24
last Monday 1555275600 2019-04-15 00:00:00 2019-04-21 05:38:24

Разбор timestamp():

                       array getdate(int $timestamp)

Возвращает ассоциативный массив, содержащий данные об указанном времени. В массив будут помещены следующие ключи и значения:

- seconds — секунды;

- minutes — минуты;

- hours — часы;

- mday — число;

- wday — день недели (0 означает воскресенье, 1 — понедельник, и т. д.);

- шоn — номер месяца;

- year — год;

- у day — номер дня с начала года;

- weekday — полное название дня недели, например, Friday;

- month — полное название месяца, например, January.

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

Григорианский календарь — это календарь, который постоянно используем в своей жизни. В России он был введен Петром I в 1700 году.

Описываемые три функции представляют интерес, если понадобится автоматически формировать календари в сценариях. Все они имеют дело с так называемым форматом Julian Day Count (JDC). Ч Каждой дате соответствует свой JDC. Ведь, фактически, JDC — это всего лишь количество дней, прошедших с определенной даты (с 4714 года до н.э.).

Допустим, заданы две даты в формате дд.мм.гггг. Нужно вычислить количество дней между этими датами. Поставленная задача решается через перевод обеих дат в JDC и определение разности получившихся в¬личин.

Функция timestamp() содержит время в секундах, начиная с 1 января 1970 года. Получить данные за более ранние периоды времени (или, наоборот, за 3000-й год) нельзя:

                                 Функция 
                       int GregorianToJD (int $month, int $day, int $year)

преобразует дату в формат JDC. Допустимые значения года для григорианского календаря — от 4714 года до н.э. до 9999 года н. э.

                                 Функция 
                     string JDToGregorian(int $julianday)

Преобразует дату в формате JDC в строку, выглядящую как месяц/число/год. Можно разбить эту строку на составляющие, чтобы работать с ними по отдельности. Для этого воспользуйтесь функцией exploded:

                     $jd = GregorianToJD(10, 11, 1970);
                     echo "$jd< br>";
                     $gregorian = JDToGregorian($jd);
                     echo "$gregorian< br>";
                     $list = explode($gregorian, "/");

2440871
10/11/1970

                     mixed JDDayOfWeek(int $julianday, int $mode=0)

Последняя функция этой серии — JDDayOfWeek() — возвращает день недели, на который приходится указанная JDC-дата. Фактически, это единственное, чего не хватало бы для формирования календарика. Параметр $mode задает, в каком виде должен быть возвращен результат:

- 0 — номер дня недели (0 — воскресенье, 1 — понедельник, и т. д.);:

- 1 — английское название дня недели;:

- 2 — сокращение английского названия дня недели.:

В РНР существует множество функций для работы с другими календарями — в том числе с республиканским, юлианским и т. д.

Проверка даты:

                      int checkdate (int $ month, int $day, int $year)

Эта функция проверяет, существует ли дата григорианского календаря, переданная ей в параметрах: вначале идет месяц, затем — день, и, наконец, — год.

Функция checkdate() проверяет следующее:

- год должен быть между 1900 и 32 767 включительно;

- месяц обязан принадлежать диапазону от 1 до 12;

- число должно быть допустимым для указанного месяца и года (если год високосный).

Функция используется при автоматическом формировании HTML-календарика для указанного месяца и года. Можно определить, какие числа в месяце "не существуют", и для них вместо номера проставить пустое место.

Календарик. Функция формирования календаря за указанный месяц указанного года. Не делает никаких предположений о том, как календарь будет прорисовываться в браузере. Функция всего лишь вычисляет соответствие дней недели числам и возвращает результат в виде двумерной таблицы. Код легко может быть использован повторно:

                         < style>
					   table#calendarik td {
						   height: 50px;
						   width: 50px;
						   font-family: Arial, Helvetica, sans-serif;
						   background-color: #FC9;
						   font-size: 22px;
						   font-weight: bold;
						   text-align: center;
						   }
					   table#calendarik tr#asd td {
						   font-weight: bold;
						   background-color: #0CF;
						   }
                       < /style>
                       < ?php 
                            /* Календарь на указанный месяц и год. Массив состоит из строк,
                               соответствующих неделям. Каждая строка — массив из семи
                               элементов, которые равны числам или пустой строке.*/
                       function makeCal($year, $month) {
                       $month=date(n); // Числовое значение текущего месяца или по желанию от 1 до 12.
                       $year=date(Y); //  Текущий год или какой Вам необходим ввиде четырехзначного числа.
                       // Получает номер дня недели для 1 числа месяца. 
                       $wday = JDDayOfWeek(GregorianToJD($month, 1, $year), 0);
                       /* Корректирует его, чтобы воскресенье 
                           соответствовало числу 7, а не числу 0.*/
                       if ($wday == 0) $wday = 7;
                       $n = - ($wday - 2);/* -2 появляется потому что к $n сразу прибавляется
                                          единица ($n++) и массив начинается не 1, но с 0*/  
                       $cal = array();
                             // Цикл по строкам,
                       for ($у=0; $у< 6; $у++) {
                       $row = array();
                       $notEmpty = false;
                           // Цикл внутри строки по дням недели,
                       for ($х=0; $х< 7; $х++, $n++) {
                           // Проверяет на наличие данного дня в месяце.
                       if (checkdate($month, $n, $year)) {
                           // Да. Заполняет клетку.
                       $row[] = $n;
                       $notEmpty = true;
                        } else {
                          // Нет. Клетка пуста.
                       $row[] = "";
                           }
                        }
                         // Если в данной строке нет ни одного непустого элемента,
                       if (!$notEmpty) break;
                          // Добавляет строку в массив.
                       $cal[] = $row;
                        }
                       return $cal;
                       }
                         // Формирует календарь на текущий месяц.
                       $now = getdate();
                       $cal = makeCal($now['year'], $now['mon']-1);
                       ? >
                       < !--Шаблон вывода календаря.-->
                       < table border="1" >
                       < tr>
                       < td>Пон< /td>
                       < td>Вт< /td>
                       < td>Ср< /td>
                       < td>Чет< /td>
                       < td>Пят< /td>
                       < td>Суб< /td>
                       < td style="color: C00;">Вос< /td>
                       < /tr>
                       < !--цикл no строка -->
                       < ?foreach($cal as $row) {? >
                       < tr>
                       < !-- цикл no столбцам -->
                       < ?foreach ($row as $i=>$v) {? >
                       < !--воскресенье — "красный" день -->
                       < td style="< ?=$v==date (d)?'color: C00' : ' '?> 
                       < ?=$v? $v : "$nbsp;"? >
                       < /td>
                       < ?}? >
                       < /tr >
                       < ?}? >
                       < /table>
                       

Теперь Вы можете полюбоваться на свой проделанный труд в виде маленького календарика на текущий месяц $month=date(n) и на текущий год $year=date(Y) или можете ставить любое числовое значение нужного Вам месяца от 1 до 12 и четырехзначное число требуемого года: что находится в вернем углу левой колонки(left-sitebar)

Дата и время по Гринвичу. Локальное время — показывают часы в том часовом поясе, где работает сервер. Допустим, Вы находитесь во Екатеринбурге, а Ваш хостинг-провайдер — в Москве. Вы заметите, что выдаваемое функциями time() и date() время отличается от времени Екатеринбурге на два часа. Это происходит потому, что скрипт ориентируется на текущее время сервера, а не на местное время пользователя, запустившего сценарий из браузера.

Время по GMT. Для того чтобы не путаться в часовых поясах, придумали специальный формат времени — гринвичский ( Greenwich Mean Time, GMT; обозначающая — UTC). Время по Гринвичу — это то время, которое в настоящий момент показывают часы в г.Гринвич в Англии. Там же проходит знаменитый "нулевой меридиан”. Для обозначения времени в других часовых поясах принята запись gmt +ччоо или gmt +чч:00, где чч — разница времени в часах. Например, обозначение Москвы — gmt +0300. Это означает, что время в Москве на 3 часа отличается от времени нулевого меридиана ( в большую сторону).

Выше были функции, " ничего не знающие" о текущем часовом поясе. Эти функции всегда работают так, будто бы находитесь в г.Гринвич, и не делают поправки на разность времени.

В РНР существует ряд функций, которые принимают в параметрах локальное время и возвращают различным образом оформленные даты, которые в текущий момент актуальны на нулевом меридиане. Это функция gmdate(), предназначенная для получения строкового представления даты по GMT, или функция gmmktime(), создающая timestamp-формат по указанной локальной дате.

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

Пусть, например, сервер расположен в Москве. Скрипт для добавления сообщения был запущен кем-то в 2 часа ночи. Так как Москва — это GMT +03:00, в базе данных сохранится отметка: текст добавлен в 23 часа по Гринвичу. [Лучше хранить время по GMT в базе данных: теперь, если скрипт "переедет" на другой сервер в другой стране, базу данных не придется менять. Этим абсолютное время похоже на абсолютные координаты в математике: оно не зависит от "системы отсчета".] Через некоторое время на форум-сервер заглянул пользователь из Сеула (GMT +09:00). Скрипт вывода сообщения определяет его временное смещение, извлекает из базы данных время по GMT (а это 23 часа) и добавляет 9 часов разницы. Получается 8 часов утра. Эта дата и выводится в браузер.

Что нужно делать для реализации данного алгоритма? смотрите:

- Получение текущего timestanip-формата по GMT. Именно этот timestamp в настоящий момент "показывают часы" в Гринвиче - сохранять данное время в базе данных.

- Получение текстового представления даты, если известен GMT-timestamp и целевая часовая зона, которая отлична от GMT - будет распечатано в браузере пользователя.

Однако, ни одна стандартная функция РНР не может справиться одновременно с обеими задачами! Функции gmtime() (по аналогии с time()) не существует. Функция gmdate(), хоть и имеет префикс gm, выполняет обратную операцию: возвращает текстовое представление даты по GMT, зная локальное время: нужно — наоборот.

Перевод времени. Для начала посмотрим, как же можно получить время по GMT, зная только локальный timestamp. Напишем для этого функцию local2gm():

                     < ?php 
                     ## Работа с временем по GMT.
                         /*Вычисляет timestamp в.Гринвиче, который 
                          соответствует локальному timestamp-значению */
                     function local2gm($localStamp=false) {
                     if ($localStamp===false) $localStamp=time();
                        //Получает смещение часовой зоны в секундах.
                     $tzOffset=date("Z", $localStamp);
                        // Вычитает разницу — получает время по GMT. 
                     return $localStamp - $tzOffset;
                      }
                       /* Вычисляет локальный timestamp в Гринвиче, который 
                          соответствует timestamp-значению по GMT.*/
                       /*Можно указать смещение локальной зоны 
                         относительно GMT (в часах),  тогда будет осуществлен 
                         перевод в эту зону, а не в текущую локальную.*/
                     function gm21ocal($gmStamp=false, $tzOffset=false) { 
                     if ($gmStamp===false) return time();
                        //Получает смещение часовой зоны в секундах
                     if ($tzOffset===false)
                     $tzOffset = date("Z", $gmStamp);
                      else
                       $tzOffset *= 60*60;
                        //Вычитает разницу — получает время по GMT. 
                     return $gmStamp + $tzOffset;
                       }
                     ? >

Здесь имеется функция gm2local(), решающую вторую часть задачи. Функция gm2local() получает на вход timestamp-значение по Гринвичу и вычисляет, чему будет равен этот timestamp в указанном часовом поясе ( по умолчанию — в текущем). Обе функции используют спецификатор "Z" функции date(). Спецификатор "Z" возвращает смещение ( в секундах) текущей часовой зоны относительно Гринвича. Это чуть ли не единственный способ в РНР для получения данного смещения.

Завершаем решение задачи:

- При добавлении записи в базу данных вычисляем время, вызвав функцию local2gm(time()).

- Для отображения времени из базы данных в браузер пользователя вызываем сле¬дующую команду:

                      echo date($format, gm2local($stampGMT, $tz))

Здесь предполагается, что переменные хранят следующие значения:

- $ format — строка форматирования даты (например, "Y-m-d H:i");

- $stampGMT — формат timestamp по Гринвичу, полученный из базы данных;

- $tz — часовая зона пользователя (смещение в часах относительно нулевого меридиана).

Можно определить часовой пояс пользователя, который запустил скрипт из браузера? Нет: в протоколе HTTP не существует заголовков запроса, предназначенных для передачи этой информации. Остается единственный метод — запросить зону у пользователя явно (например, при регистрации в форуме) и сохранить ее где-нибудь для дальнейшего использования ( можно в cookies).

Здесь применяется функция date(), которой передается локальное время, потому что функция date() не делает никаких поправок на разницу часовых поясов, а просто выводит данные в том виде, в котором они ей передаются. Задача работы с локальным и "абсолютным" временем возложена на плечи двух функций — local2gmt) и gm2local().


seosait21.ru
HTML

seosait21.ru
CSS

seosait21.ru
Web-диз.
HTML ссылка CSS ссылка ...

seosait21.ru
JavaScript

seosait21.ru
PHP

seosait21.ru
JQuery
JavaScript ссылка PHP ссылка JQuery ссылка

seosait21.ru
SEO.

seosait21.ru
MySQL

seosait21.ru
XML
... ... ...

обратно на главную     назад    дальше     вперед