Обнаружение перехода на летнее время в PHP

Мне нужно отправить электронное письмо пользователям из любой точки мира в 9:00 по местному времени. Сервер находится в Великобритании. Что я могу сделать, так это установить разницу во времени между каждым пользователем и временем сервера, которая тогда отлично работала бы, если бы не существовало летнего времени.

Вот пример, иллюстрирующий это:

  • Джон работает в Нью-Йорке, -5 часов от времени сервера (Великобритания).
  • Ричард работает в Лондоне, Великобритания, поэтому разница с сервером 0 часов.

Когда сервер переходит с GMT на GMT +1 (BST) в 2:00 в определенное воскресенье, это означает, что у Джона теперь разница во времени -6H.

Этот сценарий я все еще могу обработать, обновляя всех пользователей за пределами локального времени сервера, но как только я переместил вперед/назад время всех других пользователей, мне все равно нужен способ определить когда ( время и дата) пользователи, живущие за пределами Великобритании, изменят (или не изменят) свое местное время на вероятное летнее время.

Мне нужен метод PHP, чтобы узнать/обнаружить, когда другие части мира войдут/выйдут из летнего времени.


person Nicolas    schedule 27.05.2011    source источник


Ответы (3)


Вам нужно знать все детали перехода на летнее время самостоятельно? или вам просто нужно знать, когда в данном часовом поясе 9:00?

Если это последнее, PHP может использовать базу данных часовых поясов вашей операционной системы, чтобы сделать это за вас. Функция strtotime() удивительно хорошо "выясняет", что вы иметь в виду:

echo strtotime("today 9:00 am America/New_York");  // prints "1306501200"
echo strtotime("today 9:00 am Europe/London");     // prints "1306483200"

Просто убедитесь, что вы используете один из часовых поясов, поддерживаемых PHP.

person squirrel    schedule 27.05.2011
comment
Поскольку я уже использую strtotime в нескольких местах своего кода, я думаю, что ваш ответ является лучшим, даже если мне еще многое предстоит сделать, в частности, интегрировать это в мою работу crontab (я буду использовать тег TZ=). Ваше здоровье - person Nicolas; 01.06.2011
comment
это не сработает, если время указано в DST, особенно когда оно равно -1. - person GorillaApe; 14.05.2012
comment
@GorillaApe Ты уверен? Это должно работать независимо от того, приходится ли указанный день на летнее время или нет, если правильно выполнить преобразование для этого города. Однако обратите внимание, что когда вы используете date() впоследствии с этой меткой времени, он использует часовой пояс по умолчанию, установленный с помощью date_default_timezone_set()! - person Gregory Magarshak; 30.01.2018

Как указывает Джимми, вы можете использовать переходы часовых поясов, но это недоступно в PHP 5.3. поскольку dateTimeZone() - это PHP >= 5.2.2, а getTransitions() с аргументами - нет! В этом случае вот функция, которая может предоставить вам данные о часовом поясе, в том числе в летнее время или нет.

function timezonez($timezone = 'Europe/London'){
    $tz = new DateTimeZone($timezone);
    $transitions = $tz->getTransitions();
    if (is_array($transitions)){
        foreach ($transitions as $k => $t){
            // look for current year
            if (substr($t['time'],0,4) == date('Y')){
                $trans = $t;
                break;
            }
        }
    }
    return (isset($trans)) ? $trans : false;
}

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

date_default_timezone_set('Europe/London');
$bool = date('I'); // this will be 1 in DST or else 0

... или укажите отметку времени в качестве второго аргумента для date(), если вы хотите указать дату и время, отличное от вашего текущего времени сервера.

person Owen    schedule 14.06.2012
comment
для меня игнорировать летнее время: часовой пояс по умолчанию Европа/Париж, если (date('I')==1){ date_default_timezone_set('Europe/London');} потому что я хочу всегда UTC+1 - person khaled_webdev; 24.07.2013
comment
@khaled_webdev: тогда используйте часовой пояс +01:00. - person hakre; 20.10.2014
comment
date("I") помог мне с соответствующим вопросом. Удобно иметь логическое значение - person Stephen R; 23.06.2020

Немного изменив свой ответ: DateTimeZone::getTransitions похоже, что это подойдет что вам нужно, если у вас есть PHP >= 5.2.

Из комментария в документации:

<?php 
$theTime = time(); // specific date/time we're checking, in epoch seconds. 

$tz = new DateTimeZone('America/Los_Angeles'); 
$transition = $tz->getTransitions($theTime, $theTime); 

// only one array should be returned into $transition. Now get the data: 
$offset = $transition[0]['offset']; 
$abbr = $transition[0]['abbr']; 
?>

Итак, здесь все, что нам нужно сделать, это передать часовой пояс, который мы хотим проверить, и мы можем узнать, находится ли этот часовой пояс в DST / каково смещение. Затем вам нужно будет проверить смещение относительно GMT, чтобы узнать, хотите ли вы отправить свое электронное письмо сейчас или нет.

person Jimmy Sawczuk    schedule 27.05.2011
comment
Привет, Джимми, не могли бы вы быть более точным в своем ответе, а не просто дать мне функцию PHP. Это не очень помогает мне решить эту проблему. Здоровья, Николя. - person Nicolas; 27.05.2011
comment
@Nicolas - вам нужно найти часовой пояс в массиве, а затем проверить поле dst для этого часового пояса. - person AJ.; 27.05.2011
comment
@Nicolas Я немного пересмотрел свой ответ, используя более простой метод, и предложил примечание о том, что с этим делать. Надеюсь, поможет. - person Jimmy Sawczuk; 27.05.2011
comment
@JimmySawczuk - пожалуйста, смотрите мой ответ ниже относительно этого решения на PHP ‹5.3 - person Owen; 14.06.2012
comment
Работает как шарм..!! спасибо дружище..!! - person Ritesh; 15.03.2016