Нужно обходное решение для Firefox Date() ошибка

Я работаю над графиком холста, который обновляется в реальном времени с информацией, которую мы показываем клиенту, и в процессе подготовки к изменению DST на часах. Одним из наших требований является то, что график будет функционировать, как обычно, без необходимости обновления клиентом страницы при переключении часов.

Во время работы над этой проблемой я узнал об этой ошибке с Firefox:

https://bugzilla.mozilla.org/show_bug.cgi?id=127246

В основном объект Date() в JavaScript не обновляется в Firefox, если системное время было изменено без закрытия браузера/вкладки, и поскольку мы запрашиваем API с использованием системных часов, это довольно важный проблема.

Я предполагаю, что это не исправлено, так как билет по-прежнему отмечен как "NEW", и я также уверен, что это вызывает проблему, а не другую часть моего кода, так как я могу получить текущее время системных часов после его изменения в Firefox без необходимости обновления страницы?

FYI версия Firefox, которую я использую, - это 19.0.2

Заранее спасибо

Пример

Установите системные часы на 12:00 и откройте веб-приложение...

var currentHour = new Date().getHours() //returns 12

Установите системные часы на 13:00 без повторного открытия веб-приложения.

var currentHour = new Date().getHours() //returns 12

Ответ 1

Использовать веб-работников

Вместо того, чтобы создавать новое окно как ответ Sergiu Toarca, создайте нового веб-рабочего каждый раз, когда вам потребуется обновление. Firefox будет обновлять объект Date() всякий раз, когда создается новый веб-рабочий.

function currDate() {
    var blob = new Blob([""]),
        blobURL = window.URL ? window.URL.createObjectURL(blob) : window.webkitURL.createObjectURL(blob),
        worker = new Worker(blobURL);
    worker.terminate();
    return new Date();
}

Вы можете использовать его как обычный объект Date():

currDate().getHours(); // Gives you an updated hour

См. DEMO (работает в Firefox 19).

Ответ 2

Вы никогда не сможете полагаться на клиентскую сторону, чтобы в любом случае установить правильную дату/время. Единственным обходным решением, о котором я могу думать, является запрос текущего времени из другого источника, например. сервера.

Если вы не хотите удалять свой собственный сервер, вы можете найти открытый API, который возвращает временную метку, например, вид API времени, или службу с надежное время работы, например, eBay Client Alerts API, например:

http://clientalerts.ebay.com/ws/ecasvc/ClientAlerts?callbackname=hello&callname=GetPublicAlerts

hello({"Timestamp":"2013-03-22T14:43:21.757Z","Ack":"Failure","Errors":[{"ShortMessage":"Missing required input element.","LongMessage":"Required input element is missing from the request.","ErrorCode":"1.19","SeverityCode":"Error","ErrorParameters":[{"Value":"ChannelDescriptor","ParamID":"0"}],"ErrorClassification":"RequestError"}],"Build":"E809_CORE_BUNDLED_15739296_R1","Version":"809"});

Игнорировать все и просто получить метку времени UTC. Просто убедитесь, что вы не выбрасываете ад из какого-либо сервера для данных, которые вам действительно не нужны!

Ответ 3

Для этой проблемы существует простой (но очень хакерский) обходной путь. Вы можете создать новое окно (которое по какой-то причине сбрасывает кеш текущего окна), получить дату оттуда и сразу закрыть окно.

var getRealDate = function() {
    var w = window.open();
    var ret = new Date();
    w.close();
    return ret;
};

Посмотрите, как работает jsfiddle. Нажмите кнопку, затем измените часовой пояс, затем нажмите кнопку еще раз, и вы получите обновленное значение.

Примечание: проверено только в Firefox 19

Ответ 4

Как вы говорите о обновлениях в реальном времени на холсте, я предполагаю, что вы используете какую-то технологию push, например, используя веб-сокеты или некоторые поддельные технологии push, такие как длительный опрос AJAX.

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

Таким образом, вы можете убить двух птиц одним камнем (извините за боевое выражение, но как они говорят;)):

  • У вас есть один центральный такт, на который вы можете положиться: ваш сервер.
  • Вы используете существующую инфраструктуру обновления данных и больше не нуждаетесь в ней.
  • Клиенты могут устанавливать свои часы на все, что захотят, они всегда будут иметь правильные данные.

Все ваши клиенты должны сделать это, чтобы получить часовой пояс, в котором они находятся, и затем добавить или вычесть разницу в часовой пояс, который доставляется сервером. Например, если ваш клиент находится в UTC + 1, а ваш сервер - UTC + 4, то просто вычтите 3 часа с каждой отметки времени, которую предоставляет ваш сервер.

По мере того, как изменения DST появляются только два раза в год, вы можете даже жестко закодировать это в своем клиенте и использовать два разных алгоритма сложения/вычитания. Какой из них вы должны использовать, вы можете решить в зависимости от даты, на которую указывает время, которое сервер отправляет вам.

Таким образом, вы должны решить все свои проблемы, он работает в каждом браузере и не зависит от настроек времени клиента.

Надеюсь, что это поможет: -)

Ответ 5

Здесь супер-простое решение для конкретной ситуации с ОП, учитывая, что следующие предположения, которые я сделал (на основе того, что написано в его вопросе и комментариях), верны:

  • график предназначен только для одного клиента
  • график будет загружен в первую очередь на Firefox (версии с одинаковой ссылкой)
  • машина (и) клиента находится/находится на базе в GMT (которая становится BST при смене часов)
  • машинные часы являются/являются достаточно точными.
  • клиент не будет менять время работы машин.

Если вышесказанное верно (возможно, даже не все), это становится довольно простым. Поскольку вас действительно беспокоит только два часовых пояса, GMT и BST, вы можете адаптировать свой пример следующим образом:

Добавьте этот бит кода при загрузке/инициализации графика:

// given a date object, returns the actual hour (works for GMT/BST only)
var getDisplayHour = (function() {
  var initiallyGMT = (new Date().toString().indexOf('BST') === -1);
  return function ( date ) {
    var isGMT = (date.toString().indexOf('BST') === -1);
    var offset = initiallyGMT - isGMT;
    return date.getHours() + offset;
  }
})();

Установите системные часы на 12:00 и откройте веб-приложение...

var currentDisplayHour = getDisplayHour( new Date() ); // returns 12

Установите системные часы на 13:00 без повторного открытия веб-приложения.

// the referenced bug keeps the same time, but it successfully changes the time zone, so:
var currentDisplayHour = getDisplayHour( new Date() ); // returns 13

Протестировано на FF 19.0.0.2 на Mac и Windows 7.

Примечание.. Поскольку я действительно не мог воспроизвести проблему с OP, и, учитывая цитируемый вариант использования, я даже не уверен, что есть необходимость в любом из этих обходных решений. Можно было бы ожидать более точного теста на случай использования ОП, чтобы связать изменение времени и зоны. Например. не только 12:00 → 13:00, но 12:00 GMT → 13:00 BST. Еще более точное моделирование переключения DST состояло бы в том, чтобы установить часы на 2013-03-31 00:59:00 по Гринвичу, проверить new Date().getHours(), подождать пару минут, а затем снова проверить час.

Но, как я уже сказал, я не смог воспроизвести указанную ошибку сам, поэтому я определенно ошибаюсь (в этом случае я исправлю или удалю этот ответ).

Надеюсь, это поможет, во всяком случае!