Я изо всех сил пытаюсь обрабатывать даты и время в среде 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.
Любая помощь приветствуется.
Спасибо @RobG. Чтобы это сработало, мне понадобится часовой пояс места события. В некоторых случаях мы не будем знать местоположение. Мы получили бы дату и время от местоположения пользователя (который публикует данные).
В MongoDB/JavaScript Date объекты имеют время UTC - всегда и только!
Если вам нужно сохранить введенный часовой пояс от пользователя, вы должны сохранить его в отдельном поле. Затем ваше приложение может отображать время в часовом поясе на основе входных данных.
Почти в любой функции «дата-в-строку» вы можете предоставить информацию о часовом поясе для желаемого вывода.
Это имеет смысл, однако применительно к моему сценарию я этого не испытываю. например Я использую следующее для объединения: новая дата (${savedEvent.date.toISOString().slice(0, -1).substring(0, 10)} ${savedEvent.deliveryTime}) Локально: преобразуется во время UTC, как и ожидалось. AWS (EB): использует местный часовой пояс. Я могу точно указать это на новую дату, но не знаю, как решить
Поэтому, когда я возвращаюсь к основам и сохраняю новую дату(), она работает, как и ожидалось, на обоих серверах. Поэтому это связано с манипуляциями со строками при объединении двух полей (данные и время) - я буду продолжать, пока не получу результат
Чтобы разобрать строку в объект Date, я предлагаю готовые библиотеки, такие как moment.js , Luxon или Day.js. Обычно они намного лучше нативных Date методов JavaScript.
new Intl.DateTimeFormat().resolvedOptions().timeZone
возвращает представительное местоположение IANA для хоста, чтобы вы могли его использовать (при условии, что оно согласуется с датой и временем, которые предоставляет пользователь).
Функциональность даты и времени может сбивать с толку, поэтому лучше сделать все как можно проще. Обычно рекомендуется хранить все в формате 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, вы можете создать временную метку для любого часового пояса, в том числе для самого события.
Вероятно, гораздо лучше хранить все в формате UTC вместе со смещением или часовым поясом места, где происходит событие. Таким образом, вы можете отображать даты и время в контексте текущего местоположения пользователя, места события или UTC.