получить смещение часового пояса другого часового пояса в javascript без использования строк

Я хочу рассчитать смещение от «времени пользователя» до «WET / WEST».

Я получаю компенсацию пользователей новым Date().getTimezoneOffset().

Но как мне получить смещение для WET / WEST, чтобы я мог вычислить комбинированное смещение для обоих?

Например, если пользователь находится в центральноевропейском времени (CET / CEST), зимой комбинированное смещение будет -60 (CET) + 0 (WET) = -60. Летом это будет -120 (CEST) + 60 (WEST) = -60. В этом случае всегда -60, но у пользователя также может быть часовой пояс без летнего времени.

Возможно ли это без форматирования его в строку и считывания нового часового пояса из этой строки?


person Jens    schedule 09.03.2016    source источник
comment
Поскольку объекты Date являются в основе UTC, вы можете игнорировать местный часовой пояс и просто применить любое смещение к частям UTC, а затем прочитать новые значения UTC. Вы не можете надежно прочитать часовой пояс по результату Date.prototype.toString, поскольку он зависит от реализации. Часовой пояс может отсутствовать, быть неоднозначным или неразборчивым.   -  person RobG    schedule 09.03.2016
comment
Но где мне взять смещение для WET? Я ищу что-то вроде нового часового пояса (WET) .getOffset   -  person Jens    schedule 09.03.2016
comment
Для этого вам нужно будет создать свою собственную утилиту, возможно, на основе базы данных часовых поясов IANA , который широко используется. Я не вижу необходимости в конструкторе, часовые пояса - это простые вещи со смещением от UTC, поэтому myDateLib.getTimezoneOffset('WET') или myDateLib.getTimezoneOffset('LHDT') или myDateLib.getTimezoneOffset('Australia/Lord_Howe').   -  person RobG    schedule 09.03.2016


Ответы (2)


Аббревиатуры часовых поясов нельзя надежно использовать для ввода, поскольку их можно интерпретировать по-разному. Например, CST может быть либо «Центральное стандартное время» в Северной Америке, либо «Китайское стандартное время», либо «Стандартное время Кубы». Хотя некоторые сокращения, такие как WET и WEST, уникальны, многие из них неоднозначны. См. список сокращений часовых поясов здесь.

Вместо этого вам нужно знать идентификатор часового пояса IANA. Одно место, , в котором используется WET / WEST, - это Португалия, которая является идентификатором IANA для "Europe/Lisbon". Список идентификаторов можно найти здесь. Выбор правильного идентификатора важен, поскольку часовые пояса меняются со временем. Каждый идентификатор отражает конкретную историю каждого региона.

Если вы знаете идентификатор часового пояса IANA, у вас есть варианты его использования:

  1. В некоторых современных браузерах, которые полностью поддерживают функции часовых поясов ECMAScript Internationalization API (ECMA-402), вы можете сделать следующее:

    var d = new Date();
    var s = d.toLocaleString(undefined, { timeZone: "Europe/Lisbon" })
    

    Это преобразует предоставленные дату и время в правильный часовой пояс во время форматирования. Передача undefined в первом параметре будет использовать текущий языковой стандарт для форматирования.

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

  2. Вы можете рассмотреть возможность использования библиотеки, реализующей эту функцию. Я перечисляю некоторые из них здесь. Лично я предпочитаю moment.js с момент-часовой пояс, с помощью которого вы можете сделать следующее:

    var m = moment.tz("Europe/Lisbon");
    var s = m.format();
    

    Вы можете передать параметры методу format для отображения вывода, как вам нравится. Вы также можете преобразовать существующее время, например:

    var m = moment.utc("2016-01-01T00:00:00").tz("Europe/Lisbon");
    var s = m.format();
    

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

    var m = moment.utc("2016-01-01T00:00:00").tz("Europe/Lisbon");
    var offsetInMinutes = m.utcOffset();
    var offsetAsString = m.format("Z");
    
  3. Вы можете написать свой собственный код для обработки определенного часового пояса. Хотя это может быть подвержено ошибкам, и я обычно не рекомендую это. Обновления могут быть особенно трудными, если вы пойдете по этому пути.

Также имейте в виду, что смещение для определенного часового пояса будет варьироваться в зависимости от действующей даты и времени. Следовательно, new Date(), который представляет «сейчас», может или не всегда может быть правильным вводом, в зависимости от вашего сценария.

person Matt Johnson-Pint    schedule 09.03.2016
comment
О №1. Хорошо, поэтому я могу изменить дату на определенный часовой пояс. Но мне (и оператору) нужно вычислить разницу в часовом поясе между текущим часовым поясом пользователя и произвольным. Итак, в вашем примере: какая разница (в часах, секундах и т. Д.) Между d и s? - person Botis; 18.09.2019

Я хотел сделать это без использования библиотеки, поэтому я написал эту функцию, которая дает вам смещение часового пояса между заданным часовым поясом и utc:

function getTimezoneOffsetFrom(otherTimezone) {
    if (otherTimezone === void 0) { otherTimezone = "Europe/Amsterdam"; }
    var date = new Date();
    function objFromStr(str) {
        var array = str.replace(":", " ").split(" ");
        return {
            day: parseInt(array[0]),
            hour: parseInt(array[1]),
            minute: parseInt(array[2])
        };
    }
    var str = date.toLocaleString(['nl-NL'], { timeZone: otherTimezone, day: 'numeric', hour: 'numeric', minute: 'numeric', hour12: false });
    var other = objFromStr(str);
    str = date.toLocaleString(['nl-NL'], { day: 'numeric', hour: 'numeric', minute: 'numeric', hour12: false });
    var myLocale = objFromStr(str);
    var amsterdamOffset = (other.day * 24 * 60) + (other.hour * 60) + (other.minute);
    var myLocaleOffset = (myLocale.day * 24 * 60) + (myLocale.hour * 60) + (myLocale.minute);
    return myLocaleOffset - amsterdamOffset + date.getTimezoneOffset();
}

Возможно, его можно одобрить, используя en-US в качестве строки локали, а затем str.replace, возможно, потребуется отфильтровать запятую или что-то в этом роде.

person Johan Velthuis    schedule 04.03.2021