Тема часовых поясов в отношении веб-страниц поднимается очень редко. Иногда все же приходится вычислять часовые пояса в JavaScript.
Как правило, на странице можно получить текущее время пользователя, которое может быть преобразовано в «универсальное координированное время». Но это время может быть как «зимним», так и «летним » (с поправкой на 1 час). Чтобы проверить, нужно ли использовать поправку или нет, сделаем сравнения часовых поясов для данного региона зимой и летом. В качестве тестовых точек возьмем даты «1 февраля» и «1 августа».
var s,
now = new Date(),
nowTZ = now.getTimezoneOffset(),
winterTZ = new Date(now.getFullYear(), 1, 1).getTimezoneOffset(),
summerTZ = new Date(now.getFullYear(), 7, 1).getTimezoneOffset();
if (winterTZ === summerTZ) {
s = 'no daylight saving';
} else {
if (nowTZ === winterTZ) {
s = 'winter time';
} else if (nowTZ === summerTZ) {
s = 'summer time';
} else {
throw new Error('Unknown time zone');
}
}
В некоторых странах (например, Япония, Китай, большая часть Африки и Южной Америки) перевод на «летнее время» не используется и это можно определить, если часовой пояс зимой и летом не будет отличаться. Если переход на «летнее время» все-таки используется, то проверяем, какой часовой пояс сейчас используется – летний или зимний.
Обновление от 31 октября 2011 года : В России с 5 августа 2011 года вступил в силу «Закон об исчислении времени», отменяющий сезонный перевод часов. Печальной новостью стало то, что в Windows (начиная с XP и заканчивая 7 со всеми последними обновлениями) часовые пояса для дат в прошлом определяются не верно. В браузерах, запущенных нa OSX или Linux, такой проблемы с часовыми поясами для дат в прошлом не возникает.
Коментарии к заметке
А можешь описать задачу, для которой понадобилось узнать летнее и зимнее время?
Дело было так. Сервер работает по московскому времени. Пишет некую статистику в базу тоже в московском времени. Пользователи обращаются к этой статистике находясь в разных часовых поясах. У них есть кнопка «Сейчас», которая устанавливает в поле ввода текущее время. Но им нужно текущее время не в их часовом поясе, а в московском. Такого сорта функция позволяет правильно скорректировать время относительно UTC.
Изначально она делалась вообще для другой задачи. На сайте http://icfo.ru/ тикают трое часов (Москва, Нью-Йорк, Токио). Вот, собственно, там и использовалась поправка на летнее время, если она была нужна для Москвы и Нью-Йорка (в Токио нет летнего времени). Грядущей зимой московские показания на этом сайте собьются, если не обновить скрипт.
столкнулся с проблемой, что для дат в прошлом getTimezoneOffset определяется по разному в разных операционках Windows и MacOS, что-нибудь изменилось с 2011, можеть появился патч, кототый все лечит? возможно решить эту проблему самостоятельно?
Мне не известна подобная библиотека или патч.
Сейчас все браузеры пользуются средствами ОС, чтобы получить информацию о зона. OS X и Linux хранят все изменения смещений по времени для всех регионов. По этому ОС может правильно сообщить какой был часовой пояс в указанном регионе. Windows оперирует только самой актуальной информацией о зонах и ничего не помнит о предыдущих данных.
Вашу проблему можно решить локально, например, только для России. Если точно известен регион, в котором находится пользователь, то по заранее составленным таблицам вычислять его зону для конкретной даты. Знания о регионе нужны потому, что смещения в 2011 году происходили не только для всей страны, но и для отдельных её регионов (Самарская и Кемеровская области, Камчатка и Чукотка). В XX веке тоже была масса изменений региональных часовых поясов.
Спасибо за ответ, Уже копаюсь с этой проблемой уже целый день и чувствую, что запутываюсь все сильнее, не понимаю кто не прав. у javascript new Date(0) = 1970… 04:00, московская временная зона у java.sql.Time(0) = 03:00, московская временная зона Формально оба правы javascript сейчас сдвиг 4 часа, а java в 1970 году сдвиг был 3 часа. а описанное Вами поведение Windows и Linux + MacOS, справедливо только для Firefox, Chorome и Safari не зависят от OS. Chome, Safari, IE возвращают getTimezoneOffset() = 240 для всех дат (до и после 2011) и только Firefox под Linux и MacOS возвращает getTimezoneOffset() = 180 для дат < 2011 и 240 > 2011 Получается, что Firefox на unix-подобных системах наиболее совместим с java. Что делать со своим приложением на javascript незнаю, склоняюсь к тому что серверная часть будет отдавать время на один час меньше, а пользователям скажу, чтобы не использовали Firefox на Linux и MacOS, хорошо что у нас таких нет! А вообще далее буду стараться не использовать объект Date в javascript, т.к. он хранит в себе временную зону. При наличии временной зоны в объекте все становится легче.
Кстати, проверьте правильно-ли Java на сервере обрабатывает тайм-зоны. Для неё нужно накатывать было специальный апдейт в своё время.
В вашей ситуации, кроме того, что я описал ранее, сложно посоветовать что-то ещё. Нужно разобраться в причинах необходимости всех этих манипуляций. Подозреваю, что дату можно форматировать на сервере и возвращать строку, а не количество тиков.
Когда вы явно будете передавать часовой пояс, то и подобных проблем не будет.
Я решил эту проблему в своем частном случае, по-стараюсь все объяснить. Java хранит не одно смешение TimeZone, а много, сколько было отмен переходов на летнее время, т.е. для каждой даты есть свое смешение, для 1970 это 3 часа, а для 2012 это 4 часа. Javascript, в реализациях которые я посмотрел, хранит только одно, текущее значение, не зависимо от ОС. Только Firefox отличился на Linux и MacOS, на этих ОС Firefox похоже тоже хранит разные значения. В серверной части я использовал класс java.sql.Time мне нужно только время, год в этом случае 1970 это и создало все проблемы. Я перешел на java.sql.Timestamp с фиксированным смешением года месяца и дня со значением после отмены перехода на летнее время. В клиентском приложении я использую в виде числа, т.к. меньше проблем. Получаемое число стало длинне, но это не страшно. Теперь получается, что java берет смешение 4 часа и javascript тоже использует текущее смешение 4 часа и на любой ОС и на любом броузере у меня показывает одно время. Если же опять отменят отмену :) перехода на летнее/зимнее время, нужно будет опять сдвинуть смешение в java.
Так если есть только время без привязки к дате, которое хранится в виде секунд, то уж проще было написать простые функции, которые возвращали часы, минуты и секунды, чем городить огород с Date и зонами.
Я начинал с серверной части, которая написана на java. В java есть специальный класс java.sql.Time, который преднозначен для хранения только времени. Если бы не эти проблемы с javascript все было бы хорошо. Конечно же если бы знал об этой проблеме конечно же написал свой класс в java (хотя и сейчас это еще не поздно) и кончено же пришлось писать соответствующие функции на javascript. Поразила, серьезность java, выдавать время не только в зависимости от региона (временной зоны), но и от времени!
Спасибо Вам, что поддержали в сложную минуту, в интернете практически нет ни какой информации о этой проблеме.