Объединить дату и время без UTC

Я изо всех сил пытаюсь обрабатывать даты и время в среде Javascript. Мы используем два поля ввода для получения даты и времени события. Событие должно отображать и вычислять все даты в пределах местного часового пояса. Например. если событие происходит в Мельбурне, Австралия, то я вижу местное время в Мельбурне.

Мы используем flatpickr для ввода даты и времени (2 отдельных поля).

Дата возвращает: 2022-11-18T00:00:00.000Z (т.е. нас интересует только часть даты. Время всегда 00:00:00. Оно хранится в Mongo как "date" : ISODate("2022-11-18T00:00:00.000+0000"))

Время возвращается: 09:00 AM

Я хотел бы сохранить это в нашей MongoDB как 2022-11-18T09:00:00.000.

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

Я пробовал момент и дату-fns: однако я не могу найти согласованность между серверами и браузерами. Все, что я пробовал на SO, всегда конвертирует UTC.

Любая помощь приветствуется.

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

RobG 18.11.2022 05:09

Спасибо @RobG. Чтобы это сработало, мне понадобится часовой пояс места события. В некоторых случаях мы не будем знать местоположение. Мы получили бы дату и время от местоположения пользователя (который публикует данные).

papawheelie 18.11.2022 06:26
Асинхронная передача данных с помощью sendBeacon в JavaScript
Асинхронная передача данных с помощью sendBeacon в JavaScript
В современных веб-приложениях отправка данных из JavaScript на стороне клиента на сервер является распространенной задачей. Одним из популярных...
Принципы ООП в JavaScript
Принципы ООП в JavaScript
Парадигма объектно-ориентированного программирования имеет 4 основных принципа,
Laravel с Turbo JS
Laravel с Turbo JS
Turbo - это библиотека JavaScript для упрощения создания быстрых и высокоинтерактивных веб-приложений. Она работает с помощью техники под названием...
Слишком много useState? Давайте useReducer!
Слишком много useState? Давайте useReducer!
Современный фронтенд похож на старую добрую веб-разработку, но с одной загвоздкой: страница в браузере так же сложна, как и бэкенд.
Типы данных JavaScript
Типы данных JavaScript
В JavaScript существует несколько типов данных, включая примитивные типы данных и ссылочные типы данных. Вот краткое объяснение различных типов данных...
CSS Flex: что должен знать каждый разработчик
CSS Flex: что должен знать каждый разработчик
CSS Flex: что должен знать каждый разработчик Модуль flexbox, также известный как гибкий модуль разметки box, помогает эффективно проектировать и...
0
2
55
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

В MongoDB/JavaScript Date объекты имеют время UTC - всегда и только!

Если вам нужно сохранить введенный часовой пояс от пользователя, вы должны сохранить его в отдельном поле. Затем ваше приложение может отображать время в часовом поясе на основе входных данных.

Почти в любой функции «дата-в-строку» вы можете предоставить информацию о часовом поясе для желаемого вывода.

Это имеет смысл, однако применительно к моему сценарию я этого не испытываю. например Я использую следующее для объединения: новая дата (${savedEvent.date.toISOString().slice(0, -1).substring(0, 10)} ${savedEvent.deliveryTime}) Локально: преобразуется во время UTC, как и ожидалось. AWS (EB): использует местный часовой пояс. Я могу точно указать это на новую дату, но не знаю, как решить

papawheelie 18.11.2022 13:01

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

papawheelie 18.11.2022 13:39

Чтобы разобрать строку в объект Date, я предлагаю готовые библиотеки, такие как moment.js , Luxon или Day.js. Обычно они намного лучше нативных Date методов JavaScript.

Wernfried Domscheit 18.11.2022 14:39
new Intl.DateTimeFormat().resolvedOptions().timeZone возвращает представительное местоположение IANA для хоста, чтобы вы могли его использовать (при условии, что оно согласуется с датой и временем, которые предоставляет пользователь).
RobG 19.11.2022 08:36
Ответ принят как подходящий

Функциональность даты и времени может сбивать с толку, поэтому лучше сделать все как можно проще. Обычно рекомендуется хранить все в формате UTC и конвертировать в локальный для отображения.

Одна проблема заключается в том, как получить UTC в первую очередь.

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

Чтобы затем получить правильную информацию о смещении, вы можете использовать:

new Intl.DateTimeFormat().resolvedOptions().timeZone

Который вернет местоположение представителя IANA, на которое настроена система, что, мы надеемся, соответствует дате и времени местного события. Если нет (например, пользователь может создать событие для другого часового пояса), вам потребуется поддержка библиотеки для создания подходящей отметки времени UTC (см. Расчет смещения часового пояса только для одного конкретного часового пояса).

Сохраните временную метку UTC (или объект даты) в базе данных вместе с часовым поясом события. Таким образом, вы можете сгенерировать дату и время для места события, а также эквивалентную дату и время на основе системных настроек пользователя или любого часового пояса, который вам нравится.

Например.

// Create a Date for New Year's Eve party starting
// at 8:00pm based on the user's current system settings
let event = new Date(2022,11,31, 20);

// Generate UTC timestamp
let ts = event.toISOString();

// Get the (assumed) event offset data
let tz = new Intl.DateTimeFormat().resolvedOptions().timeZone;

// Data to store:
console.info(
  `Store\n` +
  `UTC timestamp: ${ts}\n` +
  `IANA timezone: ${tz}`
); 

console.info(
  `Event local date and time\n` +
  new Date(ts).toLocaleString('en-ca', {
    timeZone: tz,
    timeZoneName: 'long'
  })
); 

// Equivalent for user in Somalia
console.info(
  `Mogadishu equivalent\n` +
  new Date(ts).toLocaleString('en-ca', {
    timeZone:'Africa/Mogadishu',
    timeZoneName: 'long'
  })
);

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

Другие вопросы по теме