JavaScript, часовые пояса и летнее время

Добро пожаловать в выпуск Еще одного вопроса о часовом поясе на этой неделе:

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


У меня есть страница. Эта страница отображается несколько раз, например: 7:28, 7:38, 7:48. Я знаю, утро или вечер. Это всегда Америка / Нью-Йорк (они не меняются при переходе на летнее время, поскольку событие, которому они соответствуют, всегда происходит в это время независимо от летнего времени). Назовем их расписанием. Я хочу выделить следующее время.

  • Это банально для людей, живущих в Америке / Нью-Йорке.
  • This is not too terrible for people living in America/Los Angeles (assuming my logic works).
    • I can take the current time of the computer in America/Los Angeles, convert it to UTC, then determine if America/Los Angeles is currently observing DST or not and determine whether America/New York should be -0400 or -0500, apply that to the UTC, and make my comparison. This hurts a little because you're still always dealing with a Date based in America/Los Angeles and not actually changing the time zone of the Date object, but I have a reliable means of rolling back (or forward) the hours from the UTC time.

Однако что происходит, когда я пытаюсь определить, соблюдается ли летнее время с компьютера в регионе, где летнее время вообще не соблюдается?

Насколько мне известно, JavaScript будет создавать объекты Date только для текущего часового пояса, а затем любое определение DST будет основано на этом объекте Date.

Мне должно быть все равно? Время в первую очередь актуально только для людей, живущих в Америке / Нью-Йорке. Я просто пытаюсь создать приложение, которое имеет смысл при просмотре из другого часового пояса, например, когда 3 часа ночи в country_without_DST и 2 часа дня в Америке / Нью-Йорке, `` расписание '' подчеркивает, что вот-вот произойдет 14:05 и не то, что в 3:05.


person Aaron    schedule 03.03.2012    source источник
comment
Можете ли вы создать минимальный пример сбоя на jsfiddle, который демонстрирует проблемное поведение? Неудачный тест qunit там был бы потрясающим.   -  person Ben Taitelbaum    schedule 03.03.2012
comment
jsfiddle.net/bBdL5. Чтобы увидеть это явление, вам нужно сначала просмотреть страницу в часовом поясе. с летним временем. Вы увидите, что два смещения возвращаются по-разному. Затем установите часовой пояс, в котором не соблюдается летнее время, закройте браузер и перезапустите его. См. Следующие два изображения: i.imgur.com/pxqIj.jpg и i.imgur.com/ZaXi6.jpg - я не знаю другого способа определить, происходит ли летнее время, чем то, Я показываю (вот как это делает Date.js)   -  person Aaron    schedule 03.03.2012
comment
Теперь, когда я создаю примеры, я думаю, что могу просто жестко закодировать некоторые даты, чтобы помочь мне определить, летнее время сейчас или нет, но если регион, который я хочу преобразовать, чтобы перестать наблюдать DST, это не сработает без кода поддержание.   -  person Aaron    schedule 03.03.2012
comment
Этот и один день в одном часовом поясе может быть другим днем ​​в другом часовом поясе (например: день до смены часового пояса в Нью-Йорке - это день смены часового пояса в то же время в Пекине). Более того, похоже, что даже страны, которые обе соблюдают летнее время, могут наблюдать их в разные дни (в ЕС и США разные дни в марте), поэтому результаты будут - по-прежнему - иногда неверными даже при расчетах в рамках наблюдения за летним временем. часовой пояс.   -  person Aaron    schedule 03.03.2012
comment
Я не понимаю, в чем проблема. Похоже, вы показали, что date.js действительно хорошо определяет смещение часового пояса для местного времени. Если вы хотите показать время в другом часовом поясе, подумайте об использовании setTimezoneOffset?   -  person Ben Taitelbaum    schedule 03.03.2012
comment
Но я не знаю, устанавливать ли его на -0500 или -0400, потому что я не знаю, соблюдают ли Америка / Нью-Йорк в настоящее время летнее время или нет.   -  person Aaron    schedule 03.03.2012
comment
en.wikipedia.org/wiki/Tz_database   -  person mplungjan    schedule 03.03.2012


Ответы (2)


Все сравнения со временем должны производиться с getTime() вашего экземпляра. Это возвращает количество миллисекунд с эпохи UTC. Летнее время не имеет значения. Вы отправляете значение getTime() на свой сервер. Затем ваши клиентские скрипты преобразуют это значение обратно в объект JavaScript Date следующим образом:

mydate = new Date(longmillisFromAnotherTZ);

Затем используйте любой метод mydate, чтобы отобразить дату так, как вам нужно. Имеет ли это смысл? Я не понимаю, в чем проблема. Хотя я был бы счастлив что-нибудь прояснить.

Изменить:

Просто чтобы быть на 100% ясным ...

Если двум разным клиентам необходимо отображать свои действия друг для друга в разных часовых поясах, я предлагаю вам использовать только значение из (new Date()).getTime(), а затем сохранить его на сервере. Затем сервер отправляет это значение каждому соответствующему клиенту. Затем клиент отвечает за отображение его в соответствующей локали.

Кроме того, если вам нужна библиотека, которая подходит для получения часовых поясов и смещений, getTimezoneOffset(), как известно, нестабильна, вам следует проверить эту библиотеку: http://www.pageloom.com/automatic-timezone-detection-with-javascript

person JP Richardson    schedule 03.03.2012
comment
Что ж, прямой связи между сервером и javascript нет, но я понимаю, к чему вы клоните. Я действительно могу заставить сервер выводить свои ms с эпохи UTC вместе с нормализованным временем EST, и я могу просто полностью игнорировать эти времена EST и сравнивать с тем, что сервер спрятал рядом с ними на странице. Это вообще то, к чему вы клонили? Я не хочу неправильно истолковать, потому что мне было достаточно сложно передать проблему, которая у меня уже есть в тексте :) - person Aaron; 03.03.2012
comment
Хорошо, я понимаю, о чем вы говорите. Ситуация в этом случае - сервер, отображающий текст на странице в EST для клиента, который может быть где угодно. Хотя мне нужно отображать время в EST на странице, я определенно могу получить время в формате UTC с тех пор - с сервером - и поместить их в атрибут данных, который я могу сравнить с JavaScript. Это должно работать и соответствует вашему предложению всегда использовать getTime () и просто полностью игнорировать преобразования между часовыми поясами. - person Aaron; 03.03.2012
comment
Забавно, у меня была такая же проблема, когда мне приходилось очищать экран от популярного спортивного сайта; я сделал именно то, что вы представляете. - person JP Richardson; 03.03.2012

Ах, думаю, я наконец понял, о чем ты говоришь. Вы хотите сказать что-то вроде: «Текущее время в Нью-Йорке - _» на основе времени, установленного на компьютере пользователя, и хотя есть поддержка (по крайней мере, в документации) для setTimezone("EDT"), нет похоже, поддерживает setTimezone("America/New York"). Вам придется либо жестко указать даты переключения между EDT и EST (на основе текущего времени по Гринвичу, которое вы можете получить с компьютера пользователя), либо использовать сторонний API (или сделать это на стороне сервера) .

person Ben Taitelbaum    schedule 03.03.2012
comment
Определенно отличный и лаконичный способ объяснить эту проблему. Я собираюсь уделить этому вопросу немного больше времени, прежде чем я определю, что лучше всего отвечает на этот вопрос, но оба существующих ответа определенно заслуживают одобрения, так что вот они ... - person Aaron; 03.03.2012