MongoDb BSON хранит дату в формате UTC

Если я попытаюсь поместить поле даты в документ (BSON) и записать его в Mongo, BSON запишет его в формате UTC. Например, свидание

DateTime dateTime = new DateTime("2015-07-01");
Document doc = new Document("date", dateTime.toDate());

будет храниться как

"date" : ISODate("2015-06-30T18:30:00Z")

в Монго. И если я получу его с помощью того же Java-драйвера, я получу его как

Wed Jul 01 00:00:00 IST 2015

Здорово. Нет ли решения для этого? Я имею в виду, почему я не могу сохранить свою дату так, как хочу? Что делать, если мне нужно запросить БД из другого часового пояса? Я буду получать другие результаты? Поле даты является важной частью Mongo с богатым набором операторов, обернутых вокруг него. И все же, почему Mongo не обеспечивает такой гибкости? Спасибо


person void    schedule 27.07.2015    source источник
comment
Что делать, если мне нужно запросить БД из другого часового пояса? Что именно ты имеешь ввиду? По сути, тип Date представляет момент времени, внутренне хранящийся в миллисекундах с эпохи Unix. Если вы не хотите сохранять момент времени, Date вам не поможет :(   -  person Jon Skeet    schedule 27.07.2015
comment
Ну, вообще лучше хранить даты в формате UTC уже в базе данных. Возможно, вам следует сделать персонал часового пояса на стороне API.   -  person Sercan Ozdemir    schedule 27.07.2015
comment
@JonSkeet Я вставил поле даты из зоны IST. Что делать, если мне нужно запросить БД из другого часового пояса? Разве я не получу соответствующую дату и время в этом часовом поясе? Как я могу сохранить дату как есть?   -  person void    schedule 27.07.2015
comment
Просто повторяю Что делать, если мне нужно запросить БД из другого часового пояса? на самом деле не говорит мне, что вы подразумеваете под этим. Значение даты ничего не знает о часовом поясе — это просто момент времени. Точно так же любой выполняемый вами запрос будет просто сравнивать это значение с другим моментом времени. Я не знаю, что вы подразумеваете под этим в данном случае, но вам нужно понять, что означает тип Date. Непонятно, какого поведения вы пытаетесь достичь.   -  person Jon Skeet    schedule 27.07.2015
comment
@JonSkeet Возможно, моя проблема связана с мгновенным хранением. Мне нужно сохранить дату как 2015-07-01. И хотел бы запросить то же самое из Индии или Лондона и получить результат 2015-07-01 в обоих случаях. Может быть, Mongo не мой прецедент db :(   -  person void    schedule 27.07.2015
comment
Действительно, вам придется либо сохранить его как другой тип, либо проанализировать исходную дату/время в формате UTC (т.е. сохранить 2015-07-01T00:00:00Z).   -  person Jon Skeet    schedule 27.07.2015


Ответы (4)


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

Если вы не хотите иметь дело со сдвигом часового пояса, просто установите местный часовой пояс на UTC, используя следующий флаг:

-Duser.timezone="UTC"
person SimY4    schedule 27.07.2015
comment
@AswinJoseRoy установите это как параметры запуска вашего приложения, т.е. java -jar yourApp.jar -Duser.timezone="UTC" - person SimY4; 28.07.2015

При использовании DateTime (из org.joda.time или java.time) создается дата с часовым поясом, и MongoDB, к сожалению, не поддерживает ее. (см. Типы BSON)

Поэтому сохранение его в формате UTC — это простое и надежное решение без потери каких-либо данных.

В качестве альтернативы вам следует взглянуть на LocalDateTime. Он не содержит DateTimeZone, поэтому ничего не нужно предварительно конвертировать.

person TAL    schedule 27.07.2015
comment
Если вы имели в виду org.joda.time LocalDateTime, это тоже не работает. - person void; 28.07.2015

У меня проблема решена путем установки моего часового пояса как UTC из самого кода.

    DateTimeZone zone = DateTimeZone.UTC;
    DateTimeZone.setDefault(zone);
person void    schedule 28.07.2015

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

new Date(fetchedDate);

Он преобразует его в местную дату.

person user42344    schedule 02.02.2019