php переход на зимнее время

Эта тема затронула меня именно в день перехода на зимнее время, таймштампы странно чудили и парадокс для меня заключался в следующем:

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);

И в завершении статьи - отличный пример построения списка всех таймзон по всем странам. Удачки господа.

Оцени публикацию:
  • 1,5
Оценили: 1


Комментарии посетителей:

  • Есть прекрасная функция date. Вот несколько примеров:
    Прошлый понедельник date('Y-m-d', strtotime("-1 Week last Monday"));
    Следующее воскресенье date('Y-m-d', strtotime("-1 Week next Sunday"));
    Прошлый месяц date('Y-m-',strtotime("last Month"))

    С помощью такой конструкции можно выцепить любую дату и время.
    07 ноября 2010, 12:15 коммент полезен : +2 # Илья
    • все верно, об этом и шла речь в данном посте :-)
      12 февраля 2011, 09:31 коммент полезен : +1 # Admin

Предложения и пожелания:

 

youtube.com/watch?v=7hFivbgIEqk

При полном или частичном использовании материалов данного сайта, ссылка на сайт "yapro.ru" обязательна как на источник информации.
Автоматический импорт материалов и информации с сайта запрещен.
Copyrights © 2007 - 2019 YaPro.Ru

Лебеденко Николай Николаевич
Ошибка в тексте? Выделите её мышкой и нажмите: Ctrl + Enter