Эта тема затронула меня именно в день перехода на зимнее время, таймштампы странно чудили и парадокс для меня заключался в следующем:
1162076399 > 1162076400
то есть:
1162076399 - 02:59:59 29.10.2006
1162076400 - 02:00:00 29.10.2006
Вывод: не стоит полагаться на определение времени например вчера, способом вычета 86400 секунд из таймштампа, т.к. в день перевода на зимнее время мы получим дату на час позже.
А вот еще один интересный момент:
(date('01.01.2016') < date('25.12.2015')) === true
На самом деле неправильно используется функция date(), сравниваются просто строки. Строки сравниваются посимвольно. Ноль меньше, чем два, поэтому сравнение немедленно возвращает true.
Правильно сравнивать даты так:
$first = DateTime::createFromFormat('d.m.Y', '01.01.2016');
$second = DateTime::createFromFormat('d.m.Y', '25.12.2015');
var_dump($first < $second);
Или так:
var_dump(strtotime('01.01.2016') < strtotime('25.12.2015'));
Найдем разницу во времени
$dateTimeFirst = new \DateTime('2000-01-10T10:34:55+00:00');
$dateTimeSecond = new \DateTime('2000-01-10T11:36:58+00:00');
$interval = $dateTimeFirst->diff($dateTimeSecond);
$format = '%h:%i:%s';// формат даты времени, обратите внимание, что он не такой, как для функции date
echo $interval->format($format);// выводит 1:2:3
Вычитаем 1 день из текущей даты
$dt = date_create('now');// предположим сейчас 2000-01-11T10:33:55+00:00
$dt->sub(new \DateInterval('P1D'));// буква P означает периодecho $dt->format(DateTime::RFC3339);// выводит 2000-01-10T10:33:55+00:00
Вычитаем 33 минуты из даты
$dt = date_create('2000-01-11 10:33:55+03');
$dt->sub(new \DateInterval('PT33M'));// T это разделитель между датой и временем (подробнее)echo $dt->format(DateTime::RFC3339);// выводит 2000-01-11T10:00:55+03:00
Прибавляем к дате 3 секунды
$dt = date_create('2000-01-11 10:00:05+03');
$dt->modify('+3 seconds');echo $dt->format(DateTime::RFC3339);// выводит 2000-01-11T10:00:08+03:00
Кажется очень удобно, но еще удобнее использовать DateInterval::createFromDateString
Конвертация даты времени из одного часового пояса в другой часовой пояс
$dt = date_create('2015-01-11 13:33:55+03');
$tz = $dt->getTimezone()->getName();$utc = new \DateTimeZone('UTC');
$timeUTC0 = $dt->setTimezone($utc)->format(DateTime::RFC3339);
Значением $tz является +03:00, а значением $timeUTC0 является 2015-01-11T10:33:55+00:00 т.к. мы указали для данной даты нулевой часовой пояс.
Работа с датой и временем в часовых поясах
Задачка: найти текущий offset (разницу) часового пояса Europe/Moscow от GMT-0
$dateTimeZoneGMT_0 = new DateTimeZone('GMT');
$dateGMT_0 = new DateTime("now", $dateTimeZoneGMT_0);
$dateTimeZone = new DateTimeZone('Europe/Moscow');
echo $timeOffset = $dateTimeZone->getOffset($dateGMT_0);
получаю 14400 секунд / 3600 секунд = 4 часа
или в процедурном стиле:
echo timezone_offset_get($dateTimeZone, $dateGMT_0);
Интересно
С датой времени можно играть и подставляя минусы или плюсы, например:
$t3 = new DateTime( '-3 day' );
$t2 = new DateTime( '-2 day' );
$dateTime = max( $t3, $t2 );// можно даже сравнивать даты функцией max
echo $dateTime->format('Y-m-d');
выводит дату $t2 т.к. она больше.
Недопонимание
Не удается найти таймзону по дате времени:
$date = new DateTime('2013-09-30 15:36:00+04');
$timezone = $date->getTimezone();
echo $timezone->getName();
выводит +04:00 а казалось должно выводить Europe/Moscow, но все работает правильно, т.к. в GTM+4 есть множество временных зон:
Europe/Moscow, Europe/Samara, Europe/Simferopol, Europe/Volgograd
Если хочется получить весь список таймзон, то сделать это можно так:
$array = DateTimeZone::listIdentifiers();// эквивалентно DateTimeZone::listIdentifiers(DateTimeZone::ALL);
print_r($array);
для европы
$array = DateTimeZone::listIdentifiers(DateTimeZone::EUROPE);
или по буквенному алиасу, например для америки:
$array = DateTimeZone::listIdentifiers(DateTimeZone::PER_COUNTRY, 'US');
Пример выбора всех таймзон-имен для GMT-4:
$dateTimeZoneGMT_0 = new DateTimeZone('GMT');
$dateGMT_0 = new DateTime("now", $dateTimeZoneGMT_0);
$array = DateTimeZone::listIdentifiers(DateTimeZone::EUROPE);
$listGMT4 = array();
foreach($array as $timeZoneName){
$dateTimeZone = new DateTimeZone($timeZoneName);
if( $dateTimeZone->getOffset($dateGMT_0)/ 3600 == 4){
$listGMT4[] = $timeZoneName;
}
}
print_r($listGMT4);
И в завершении статьи - отличный пример построения списка всех таймзон по всем странам. Удачки господа.
Комментарии
Прошлый понедельник date('Y-m-d', strtotime("-1 Week last Monday"));
Следующее воскресенье date('Y-m-d', strtotime("-1 Week next Sunday"));
Прошлый месяц date('Y-m-',strtotime("last Month"))
С помощью такой конструкции можно выцепить любую дату и время.