Скрипт для вывода времени, привязанного к конкретному часовому поясу

Я потратил почти сутки, чтобы разобраться в этом, но у меня-таки получилось…
В js есть объект Date(), который возвращает время пользователя, при помощи которого можно реализовать, например, динамические часы или таймер обратного отсчёта на странице сайта. Моей же задачей было получить и вывести на страницу время конкретной временной зоны, вне зависимости от временной зоны пользователя.

Внутри объекта Date() есть параметр, который показывает часовой пояс пользователя. Всё что нужно сделать, чтобы получить, например, московское время – вычесть из текущего времени пользователя смещение по времени, получив тем самым время по Гринвичу, и применить к получившемуся результату нужное смещение (в случае с Москвой – прибавить три часа).

Делается это довольно просто:
Для получения смещения относительно Гринвича к объекту Date() применяется метод getTimezoneOffset().
В двух словах: данный метод возвращает смещение времени пользователя относительно Гринвича в минутах со знаком “минус”. Т.е. пользователь с UTC+5 в результате работы данного метода получит -300 ( 5 * 60 ). О том откуда берётся знак “минус” можно почитать в статьях об этом методе.

Вот такой код получился в итоге:

function moveTimeZone( timezone_offset ){
    var current_timezone_offset = new Date().getTimezoneOffset();
    var now_in_selected_timezone = new Date( new Date().getTime() + timezone_offset * 3600 * 1000 + current_timezone_offset * 60 * 1000);
    return now_in_selected_timezone;
}
var userTime = Math.round(new Date().getTime()/1000);
var timeInMoscow = moveTimeZone($userTime, 3);

А теперь подробнее:
Функция:
В переменную current_timezone_offset записываем значение смещения времени во временной зоне пользователя (в минутах).
В переменную now_in_selected_timezone записываем время нужной нам временной зоны, которое получаем при помощи следующей формулы:

текущее время пользователя ( new Date().getTime() )
+
смещение времени для временной зоны, время которой мы хотим получить (в часах, по этому умножаем timezone_offset на 3600, чтобы получить значение в секундах и на 1000, для получения его же в миллисекундах)
+
смещение времени во временной зоне пользователя (так как значение для current_timezone_offset было получено в минутах, то для получения его в секундах умножаем его на 60, а следом на 1000, для получения значения в миллисекундах).

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

Конечно есть один нюанс: время на устройстве пользователя может быть неправильным, из-за чего и финальное значение не будет соответствовать действительности. Чтобы избежать подобного следует использовать время сервера, которое в PHP можно получить при помощи функции time().

p.s. Статья создана ещё в феврале 2018, а дописана только сейчас – в июне 2020. А всё дело в том, что я буквально на той неделе столкнулся с необходимостью написания таймера обратного отсчёта и долго вспоминал, как же я это делал два года назад. Решил таки задокументировать, чтобы было куда подглянуть через два года, когда я снова забуду как это делается.

p.s.s 18.11.2024 Таки пригодилось, подглядел, внёс изменения для уменьшения объёма кода


Тут могла быть ваша реклама.