ТЛ; др
ZoneId zoneId = ZoneId.of("Europe/Paris") ;
LocalDate startDate = LocalDate.of("2016-06-01") ;
ZonedDateTime zdt start = startDate.atStartOfDay(zoneId) ;
ZonedDateTime zdt stop = startDate.plusMonths(1).atStartOfDay(zoneId) ;
// Perform database search where ((x >= start) AND (x < stop)) . Notice '>=' versus '<' with no 'equals' on the latter.
Если вам нужны струны ...
String outputStart = start.toInstant().toString() ; // 2016-05-31T22:00:00Z Paris in the summer is two hours ahead of UTC.
String outputStop = stop.toInstant().toString() ; // 2016-06-30T22:00:00Z
Подробности
Answer by ishmaelMakitla хороша тем, что она указывает на использование классов java.time, встроенных в Java 8 и более поздних версий. Но он фокусируется на строках, а не на объектах. Также он не обсуждает ключевую проблему часового пояса.
Классы java.time включают в себя:
LocalDate
для даты только значения с не время-дня и без часового пояса.
LocalTime
для значения времени суток без даты и без часового пояса.
LocalDate startDate = LocalDate.parse ("2016-06-01"); // Анализ стандартного формата даты ISO 8601. LocalTime startTime = LocalTime.MIN; // '00: 00 '.
Оба этих классов могут быть использованы в фабричных методов для создания экземпляра LocalDateTime
и другие классы.
LocalDateTime ldt = LocalDateTime.of(startDate , startTime);
В коде выше мы использовали LocalTime.MIN
получить 00:00
. Чтобы напрямую ответить на ваш вопрос, вы также можете использовать LocalTime.MAX
таким же образом, чтобы получить 23:59:59.999999999
. Но я делаю не. Читайте ниже о «Half-Open».
часового пояса
Временная зона имеет решающее значение при определении даты и времени. В любой момент времени и часовом поясе изменяются по часовому поясу. Через несколько минут после полуночи в Париже новый день, пока еще «вчера» в Монреале.
Категории Local…
: не действительные моменты на шкале времени. Они представляют собой смутное представление о возможно моменты. Как отмечалось выше, первый момент 1 июня в Париже - 31 мая в 18.00 в Монреале. Поэтому перед выполнением поиска в базе данных вам необходимо назначить часовой пояс для вашего LocalDateTime
. Применение ZoneId
создает объект ZonedDateTime
.
Возможно, ваше времяпрепровождение предназначалось для Парижа.
ZoneId zoneId = ZoneId.of("Europe/Paris");
ZonedDateTime zdt = ldt.atZone(zoneId);
Возможно, вы имели в виду UTC. Все это зависит от ваших бизнес-правил, контекста, в котором работает ваше приложение. Для UTC мы используем OffsetDateTime
, так как UTC - это не полный часовой пояс, а просто offset-from-UTC. Часовой пояс - это смещение плюс набор правил для обработки аномалий, таких как летнее время (DST).
OffsetDateTime odt = ldt.atOffset(ZoneOffset.UTC);
Чтобы получить строку, как просили в вопросе, извлечь LocalDate и вызвать toString()
. Но я не рекомендую это, поскольку он игнорирует часовой пояс (см. Ниже).
String output = odt.toLocalDateTime.toString(); // Not likely to be what you really need.
Лучшая практика в базах данных заключается в том, чтобы хранить дату и время в UTC. Я не знаю о MongoDB. Обязательно прочитайте документ о том, как ваш драйвер базы данных в Java может влиять на/переводить указанные вами значения.
Начало дня
Имейте в виду, что день не всегда начинается в 00:00:00
. В некоторых часовых поясах DST или другие аномалии означает, что день может начаться в другое время, например 01:00
.
В некоторых ситуациях классы java.time будут вносить необходимые корректировки. Обязательно прочтите документ класса, чтобы убедиться, что поведение соответствует вашим ожиданиям. &.
Вы можете запросить java.time, чтобы найти время начала.
ZonedDateTime zdt = LocalDate.of("2016-06-01").atStartOfDay(zoneId);
Half-Open
Ваша попытка определить конец дня является проблемой. Эта последняя секунда бесконечно делима. Традиционные Unix-ориентированные библиотеки разрешают целые секунды, старые классы времени в Java разрешают миллисекунды, некоторые базы данных, такие как Postgres, могут разрешаться на микросекундах, а java.time и другие базы данных, такие как H2, разрешаются наносекундами. Не вставайте посреди этого.
Как правило, в программировании продолжительности времени в режиме времени наилучшая практика - «Полуоткрытая». Начало пролета включительно в то время как окончание исключая.
Так поиск в течение месяца данных в Париже зоне означает поиск записей, где дата-время равно или позже чем в начале и меньше (но не включая) упора.
ZoneId zoneId = ZoneId.of("Europe/Paris");
LocalDate startDate = LocalDate.of("2016-06-01");
ZonedDateTime zdt start = startDate.atStartOfDay(zoneId);
ZonedDateTime zdt stop = startDate.plusMonths(1).atStartOfDay(zoneId);
// Perform database search where ((x >= start) AND (x < stop)) . Notice '>=' versus '<' with no 'equals' on the latter.
Аналогичным образом, месяц записей для UTC, а не Париж.
ZoneOffset zoneOffset = ZoneOffset.UTC;
LocalDate startDate = LocalDate.of("2016-06-01");
OffsetDateTime start = OffsetDateTime.of(startDate , zoneOffset);
OffsetDateTime stop = OffsetDateTime.plusMonths(1).of(startDate , zoneOffset);
// Perform database search where ((x >= start) AND (x < stop)) . Notice '>=' versus '<' with no 'equals' on the latter.
Использование полуоткрытого подхода последовательно на протяжении всего приложения, где обработки протяжения времени сделает ваш код более разумным и легче понять. Вы также можете обучить своих пользователей думать так. Мы все используем Half-Open интуитивно в ситуациях, таких как «Перерыв на обед с 12:00 до 13:00». Мы все знаем, что это означает вернуться с обеда до часы забастовки 13:00:00.0
.
Получение и начало и конец даты как же - Начало: Чт 01 января 00:00:00 IST 1970 и Конец: Чт янв 01 00:00:00 IST 1970 – Paddy
Я обновил ответ, попробовал это – Developer