Проблемы с часовым поясом и переходом на летнее время

Я просмотрел другие решения на SO, и ни одно из них, похоже, не решает проблему часового пояса / dst в следующем отношении.

Я звоню в NOAA Tide Prediction API и API национальной метеорологической службы NOAA, которые требуют передачи временного диапазона для получения данных. Для каждого местоположения в моей базе данных у меня есть часовой пояс в виде смещения по всемирному координированному времени и указывается, соблюдается ли летнее время (1 или 0). Я пытаюсь отформатировать некоторые даты (сегодня и завтра), чтобы они соответствовали LST (местное стандартное время) в его собственном часовом поясе, чтобы я мог перейти к этим API.

Мне сложно понять, как узнать, находится ли дата, например, сегодня, в диапазоне летнего времени или нет.

Вот что у меня есть на данный момент:

// Get name of timezone for tide station
// NOTE: $locationdata->timezone is something like "-5"
$tz_name = timezone_name_from_abbr("", $locationdata->timezone * 3600, false);
$dtz = new DateTimeZone($tz_name);    

// Create time range
$start_time = new DateTime('', $dtz);
$end_time = new DateTime('', $dtz);
$end_time = $end_time->modify('+1 day');

// Modify time to match local timezone
$start_time->setTimezone($dtz);
$end_time->setTimezone($dtz);

// Adjust for daylight savings time
if( $locationdata->dst == '1' )
{
   // DST is observed in this area. 

   // ** HOW DO I KNOW IF TODAY IS CURRENTLY DST OR NOT? **  

}           

// Make call to API using modified time range
...

Как я могу это сделать? Спасибо.


person Jeremy Harris    schedule 07.03.2012    source источник


Ответы (3)


Вы можете использовать функции времени и даты PHP:

$tzObj = timezone_open($tz_name);
$dateObj = date_create("07.03.2012 10:10:10", $tzObj);

$dst_active = date_format($dateObj, "I");

Если в указанную дату активно летнее время, $dst_active равно 1, иначе 0.

Вместо указания времени в вызове date_create вы также можете передать "now", чтобы получить значение для текущей даты и времени.

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

person Chris    schedule 07.03.2012

Для каждого местоположения в моей базе данных у меня есть часовой пояс в виде смещения по всемирному координированному времени и указывается, соблюдается ли летнее время (1 или 0).

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

По сути, ваша база данных должна содержать идентификатор часового пояса, а не смещение / DST-true-or-false. (Предполагая, что PHP использует базу данных часовых поясов zoneinfo, идентификатор часового пояса будет чем-то вроде «Европа / Лондон».)

РЕДАКТИРОВАТЬ: чтобы найти смещение заданного DateTime, вы можете вызвать getOffset , который затем можно сравнить со стандартным смещением времени. Но если у вас нет окончательного идентификатора часового пояса, вы рискуете попасть не в тот пояс.

person Jon Skeet    schedule 07.03.2012
comment
Функция timezone_name_from_abbr("", $locationdata->timezone * 3600, false); возвращает идентификатор часового пояса из смещения, поэтому -5, вероятно, вернет 'America / New York'. - person Jeremy Harris; 07.03.2012
comment
@cillosis: Вы полагаетесь на точность этой карты? Потому что это будет неоднозначным. Отредактирую, чтобы ответить на конкретный вопрос ... - person Jon Skeet; 07.03.2012
comment
Я уверен, что возникнет двусмысленность, но на данный момент меня это не беспокоит. Меня больше беспокоит определение того, соблюдает ли область в настоящее время летнее время или нет. - person Jeremy Harris; 07.03.2012
comment
@cillosis: Трудно понять, что если вы не знаете, в какой области вы действительно заинтересованы ... но, как я уже сказал, вы можете позвонить getOffset в DateTime, чтобы узнать. - person Jon Skeet; 07.03.2012
comment
Вы можете поддерживать свои определения tzdata (и, следовательно, DST) в актуальном состоянии с помощью задания cron для частого обновления этого пакета PECL: pecl.php.net/package/timezonedb - person taiganaut; 17.05.2012

Циллез, надеюсь, вы не работаете с Явой! Я все время борюсь со временем. Еще я работаю с данными о погоде. Большинство данных, которые я использую, относятся к местному стандартному времени (без учета летнего времени). Мне также нужно использовать время из других часовых поясов, и я обнаружил, что Java продолжает считывать часовой пояс моего компьютера. Я также продолжал сталкиваться с устаревшими классами. Я нашел решение, которое работает. Это немного похоже на клудж, поэтому у меня есть много документации, и он существует только в одной функции. Мое решение - относительное время. Я установил местное время на UTC. Я вычитаю смещение по Гринвичу, а не добавляю его. На самом деле меня не волнует реальное время, все, что меня волнует, - это разница между двумя временами. Работает очень хорошо. Удачи

person JayneR    schedule 08.03.2012
comment
Я использую PHP и в итоге реализовал аналогичное решение. - person Jeremy Harris; 08.03.2012