Получить смещение часового пояса между двумя часовыми поясами за заданную продолжительность - PullRequest
6 голосов
/ 06 февраля 2012

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

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.

Ответы [ 3 ]

3 голосов
/ 06 февраля 2012

Предполагая, что у вас есть более новая версия 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));
2 голосов
/ 27 апреля 2018

Это работает для меня:

function Get_Timezone_Offset($remote_tz, $origin_tz = null) 
{
    if($origin_tz === null) 
    {
        if(!is_string($origin_tz = date_default_timezone_get())) {
            return false;
        }
    }
    $origin_dtz = new DateTimeZone($origin_tz);
    $remote_dtz = new DateTimeZone($remote_tz);
    $origin_dt  = new DateTime("now", $origin_dtz);
    $remote_dt  = new DateTime("now", $remote_dtz);
    $offset     = $origin_dtz->getOffset($origin_dt) - $remote_dtz->getOffset($remote_dt);
    return $offset;
}

Чтобы использовать его

echo Get_Timezone_Offset('America/New_York', 'Europe/Stockholm');

Источник: http://php.net/manual/en/function.timezone-offset-get.php

1 голос
/ 07 февраля 2012

Я думаю, что PHP DateTimeZone::getTransitions метод может привести вас туда.Он имеет процедурный псевдоним 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 ссылается на временную метку PHP в секундах эпохи, возвращаемую time(), давая момент времени, в который изменяется смещениек значению в этой записи.time относится к тому же моменту времени, что и форматированная строка даты-времени.offset - это смещение часового пояса в секундах от UTC, начиная с момента time / ts, до следующего перехода.isdst равно 1, если смещение относится к смещению перехода на летнее время, 0 в противном случае.abbr - строковое сокращение для часового пояса.Если у кого-либо есть надежная информация об этой структуре данных, было бы полезно добавить ее в документацию .

...