Получите смещение часового пояса между двумя часовыми поясами на заданную продолжительность

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

getTimezoneOffset(startDate,endDate,timezone1,timezone2){ ...missing magic to go here... } 

должен вернуть смещение часового пояса, которое действует для данной продолжительности. Однако, если смещение изменяется, оно должно вернуть диапазон дат, для которого он действителен.

Поэтому я смотрю на что-то вроде этого:

 getTimezoneOFfset("march 9 12 am", "march 15 12 am", "UTC", "US/NEW_YORK") 

вернуть значение примерно так

 timezoneoffset[0]["range"]=[march 9 12am to march 11 2 am] timezoneoffset[0]["offset"]=5 timezoneoffset[1]["range"]=[march 9 2 am to march 15 12 am] timezoneoffset[1]["offset"]=4 

Я просто не хочу вычислять смещения часовой пояс для каждого запланированного элемента для заданного диапазона. Посмотрел, есть ли способ получить прямой поиск смещений, если он изменится.

Я работаю с PHP, но решение на любом языке будет оценено.

Решение MySQL также будет работать, поскольку оно будет более оптимизировано для этого в MySQL.

Предполагая, что у вас есть более новая версия php (5.2.0+), класс DateTimeZone является частью ядра PHP и позволит вам использовать функцию getOffset() для выполнения этих вычислений. Он позволит вам передать объект dateTime и указать часовой пояс. Если вы сделаете это для обеих дат, вы сможете рассчитать все части, которые вы хотите захватить. Чтобы использовать пример из php.net:

 // Create two timezone objects, one for Taipei (Taiwan) and one for // Tokyo (Japan) $dateTimeZoneTaipei = new DateTimeZone("Asia/Taipei"); $dateTimeZoneJapan = new DateTimeZone("Asia/Tokyo"); // Create two DateTime objects that will contain the same Unix timestamp, but // have different timezones attached to them. $dateTimeTaipei = new DateTime(mktime([the date in question]), $dateTimeZoneTaipei); $dateTimeJapan = new DateTime(mktime([the date in question]), $dateTimeZoneJapan); // Calculate the GMT offset for the date/time contained in the $dateTimeTaipei // object, but using the timezone rules as defined for Tokyo // ($dateTimeZoneJapan). $timeOffset = $dateTimeZoneJapan->getOffset($dateTimeTaipei); // Should show int(32400) (for dates after Sat Sep 8 01:00:00 1951 JST). print("Number of seconds Japan is ahead of GMT at the specific time: "); var_dump($timeOffset); print("<br />Number of seconds Taipei is ahead of GMT at the specific time: "); var_dump($dateTimeZoneTaipei->getOffset($dateTimeTaipei)); print("<br />Number of seconds Japan is ahead of Taipei at the specific time: "); var_dump($dateTimeZoneJapan->getOffset($dateTimeTaipei) -$dateTimeZoneTaipei->getOffset($dateTimeTaipei)); 

Я думаю, DateTimeZone::getTransitions метод DateTimeZone::getTransitions PHP может получить вас там. Он имеет процедурный псевдоним, timezone_transitions_get() .

 public array DateTimeZone::getTransitions ( [ int $timestamp_begin [, int $timestamp_end ]] ) 

Этот метод возвращает все «переходы» из одного значения смещения часового пояса в другое для этого временного пояса в заданный временной диапазон.

Для ваших целей вам нужно создать объекты DateTimeZone для каждого из ваших часовых поясов, вызвать DateTimeZone::getTransitions для вашего диапазона дат, чтобы получить массив переходов для этого часового пояса, затем слить и отсортировать два массива переходов. Это даст вам эквивалент массива timezoneoffset[] вы ищете.

Что-то вроде:

 getTimezoneOffset(startDate,endDate,timezone1,timezone2){ DT1 = DateTimeZone( timezone1 ); transitions1 = DT1->getTransitions( startDate,endDate ); DT2 = DateTimeZone( timezone2 ); transitions1 = DT2->getTransitions( startDate,endDate ); timezoneoffset[] = // merge and sort (transitions1, transitions2) } 

Формат массива переходов плохо документирован. В документации по методу показаны некоторые примеры:

 Array ( ... [1] => Array ( [ts] => -1691964000 [time] => 1916-05-21T02:00:00+0000 [offset] => 3600 [isdst] => 1 [abbr] => BST ) [2] => Array ( [ts] => -1680472800 [time] => 1916-10-01T02:00:00+0000 [offset] => 0 [isdst] => [abbr] => GMT ) ... ) 

Я предполагаю, что: ts ссылается на time() метку PHP в секундах эпохи, возвращенную time() , давая момент времени, при котором смещение изменяется на значение в этой записи. time относится к тому же time , что и форматированная строка даты-времени. offsetoffset часового пояса в секундах от UTC, с момента time / ts , переход к следующему переходу. isdst равно 1, если смещение относится к смещению на летнее время, 0 в противном случае. abbr – это аббревиатура строки для часового пояса. Если у кого-то есть достоверная информация об этой структуре данных, было бы приятно добавить ее в документацию .