Есть ли способ переопределить `new Date ()` в Javascript, чтобы он всегда возвращал дату с учетом одного конкретного закодированного часового пояса? - PullRequest
0 голосов
/ 29 апреля 2019

Я работаю над проектом React.js, который обрабатывает множество сравнений, связанных с DateTime (сравнение часа, месяца, года и т. Д. С датами, полученными из API).Для этого конкретного приложения React.js я хотел бы всегда рассматривать DateTimes (от new Date()), как если бы пользователь находился в часовом поясе сервера.Предполагая, что сервер находится в часовом поясе "Европа / Берлин", я хотел бы, чтобы в любой точке приложения вызов new Date('2019-01-01') возвратил бы мне DateTime, который ссылается на это время в часовом поясе "Европа / Берлин", который был быTue Jan 01 2019 01:00:00 GMT+0100 (Central European Standard Time).Например, если я установлю дату и время на своем компьютере, как если бы я был в Бразилии, я получу Mon Dec 31 2018 22:00:00 GMT-0200 (Brasilia Summer Time), но хотел бы получить то же, что и раньше.Основная причина, по которой это является проблемой, заключается в том, что мы извлекаем данные из этих DateTimes, таких как .getHours(), .getDate() и т. Д.

Это подходит для этого конкретного приложения, поскольку для этого проекта очень важно, чтобы мы толькоПоддержка сервера Timezone, независимо от того, где находится пользователь.Таким образом, чтобы соответствовать времени сервера, вызов new Date('2019-01-01').getDate() должен вернуть 1, так как это будет 1 января в Берлине.Однако, если пользователь находится в Бразилии, этот же вызов вернет 31, так как Бразилия за несколько часов до GMT, когда в полночь по времени GMT, это будет все еще предыдущий день в Бразилии.

IСначала попытался использовать date-fns вместе с date-fns-timezone, чтобы установить DateTime для отображения даты и времени для клиента с учетом часового пояса сервера.Это работало нормально для отображения правильных данных, но не решало некоторые проблемы, вызванные извлечением этих атрибутов из даты, и это будет зависеть от того, где находится пользователь.

Так вот почему яПопытка сделать это переопределить метод new Date() таким образом, что он всегда будет извлекать дату, как если бы пользователь был на сервере времени.Мне не удалось понять, как это можно сделать.Всякий раз, когда я изменяю дату и время с моего компьютера, вывод для new Date() уже учитывает эти новые настройки даты и времени.

Так как же заставить new Date() всегда возвращать DateTime с жестко заданным часовым поясом?Кроме того, было бы очень хорошо, если бы я мог сделать это без использования внешних библиотек (например, moment.js) и делать это только с простым Javascript.

Я смотрел на window.navigatorпеременная, чтобы увидеть, смогу ли я установить этот параметр для принудительной установки даты в часовой пояс сервера, но, похоже, это не будет решением моей проблемы.

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

1- new Date () для определенного часового пояса в JavaScript : в этом случаеmoment используется, и не было никакого способа выполнить это переопределение для самого new Date().

2- Преобразовать строку в дату без учета часового пояса : в этомanswer возвращает строку с датой, отформатированной в желаемом часовом поясе, но не с самим объектом Date.

3- дата javascript с учетом Request.UserLanguages ​​[0] : также в этом,вопрос / ответ касается форматирования вывода даты, а не извлечения самого объекта Date с новым часовым поясом.

4- Как объединить часовой пояс moment.js с toDate для создания нового объекта даты?: в этом ответ также об использовании moment.js, чего я бы хотел избежать, поскольку я действительно хочу добиться переопределения метода new Date().

Ответы [ 2 ]

0 голосов
/ 01 мая 2019

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

Как и в этом конкретном случае, мне действительно нужно сравнить и сгруппировать некоторые объекты на основе даты, среди другихопераций (всегда учитывая часовой пояс сервера), я выбрал moment.js вместе с moment-timezone.Нативный класс Date не может решить эту проблему, поскольку он не может обрабатывать разные часовые пояса.Затем я попытался использовать сначала date-fns и date-fsn-timezone, но так как эти библиотеки всегда используют стандартный класс Date, возникает проблема, заключающаяся в том, что Date в javascript является только меткой времени и не имеет никакого представления о том,другие часовые пояса, отличные от часового пояса клиента (приложение React.js).

Просто чтобы показать один пример проблемы, рассмотрим, что сервер находится в часовом поясе Европа / Берлин, и одну отметкуизвлекается как 2019-04-30T02:00:00+02:00.В приложении React.js я хочу сгруппировать этот штамп по всем штампам, которые также относятся к 2019-04-30.Однако, если браузер работает в Brazil/Brasilia времени, вызов new Date('2019-04-30T02:00:00+02:00').getDate() вернет мне 29, поскольку в часовом поясе клиента эта же временная метка будет представлять 2019-04-29T09:00:00-03:00.

Используя moment и moment-timezone, это можно исправить, указав, в каком часовом поясе я хочу получить значения, например:

moment('2019-04-30T02:00:00+02:00').tz('Europe/Berlin').date()
// retrieves 30 independent on the client timezone.

Большое спасибо всем, кто внес вкладс ответами и предложениями.Вы все помогли мне найти путь для решения этой проблемы.

0 голосов
/ 29 апреля 2019

Несколько вещей:

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

  • Имейте в виду, что объект Dateв JavaScript это неправильно.Это действительно отметка времени .По сути, это просто объектная оболочка вокруг значения, которое вы получаете с помощью .valueOf() или .getTime() или когда вы приводите его к числу.Функция everything объекта Date просто считывает это значение, применяет некоторую логику (которая может использовать или не использовать местный часовой пояс в зависимости от функции) и генерирует некоторый результат.Точно так же конструкторы объекта Date интерпретируют ваш ввод и затем присваивают этот номер полученному объекту.Другими словами, объект Date вообще не отслеживает часовой пояс.Он просто применяет его, когда к нему обращаются.Таким образом, его нельзя изменить.

  • Когда вы передаете строку в формате yyyy-MM-dd в конструктор Date, согласно спецификации ECMAScript она интерпретируется как полночь UTC, а не как полночьместное время.Это отклонение от ISO 8601, и это часто сбивает людей с толку.

  • Строки, которые вы показали как выходные данные, такие как Tue Jan 01 2019 01:00:00 GMT+0100 (Central European Standard Time), выводятся по местному времени и являются результатом либо вызова.toString() или путем передачи объекта Date в console.log в некоторых средах.Другие среды показывают результат .toISOString(), который передается в UTC.

  • В window.navigator или где-либо еще нет глобального объекта, который мог бы изменить местный часовой пояс.В приложениях Node.js, если вам действительно нужно установить часовой пояс сервера глобально, вы можете установить переменную среды TZ перед запуском Node.Однако это не работает в средах Windows и не помогает браузерам.

  • Вы работаете с библиотекой, такой как date-fns с date-fns-timezone.Есть и другие библиотеки, которые перечислены в этом ответе .В качестве альтернативы вы можете вызвать .toLocaleString с параметром timeZone, например:

    new Date().toLocaleString("en-US", {timeZone: "America/New_York"})
    

    Этот API-интерфейс предоставляет функциональные возможности для выдачи строки в определенном часовом поясе, но он ничего не делает для применениячасовой пояс для входной строки.

Итак, в конечном итоге, чтобы ответить на ваш вопрос:

Так как я могу форсировать новую дату() чтобы всегда возвращать DateTime с жестко заданным часовым поясом?

Извините, вы не можете.Вы можете использовать другой объект для отслеживания часового пояса с указанием состояния или использовать функции, которые принимают часовой пояс в качестве параметра.Обе вещи предлагаются существующей библиотекой, но в JavaScript в настоящее время встроена только одна функция, показанная выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...