Как узнать время начала и окончания дня?
такой код не точен:
private Date getStartOfDay(Date date) {
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DATE);
calendar.set(year, month, day, 0, 0, 0);
return calendar.getTime();
}
private Date getEndOfDay(Date date) {
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DATE);
calendar.set(year, month, day, 23, 59, 59);
return calendar.getTime();
}
Это не точность до миллисекунды.
Ответы:
ТЛ; др
Начало дня
Получите полную длину сегодняшнего дня в часовом поясе.
Использование полуоткрытого подхода, когда начало включено, а окончание - эксклюзивно . Такой подход устраняет ошибку в вашем коде, которая не учитывает самую последнюю секунду дня.
Смотрите те же моменты в UTC.
Если вы хотите, чтобы весь день даты отображался в формате UTC, а не в часовом поясе, используйте
OffsetDateTime
.Эти
OffsetDateTime
объекты уже будут в формате UTC, но вы можете позвонить,toInstant
если вам нужны такие объекты, которые по определению всегда находятся в формате UTC.Совет: вас может заинтересовать добавление библиотеки ThreeTen-Extra в ваш проект, чтобы использовать ее
Interval
класс для представления этой парыInstant
объектов. Это обеспечивает класс полезные методы для сравнения , такие какabuts
,overlaps
,contains
и многое другое.Полуоткрытый
Ответ на mprivat правильно. Его цель - не пытаться получить конец дня, а скорее сравнить с «до начала следующего дня». Его идея известна как «полуоткрытый» подход, в котором у отрезка времени есть начало, включающее, а окончание - исключительное .
Joda-Time 2.3 предлагает метод для этой цели, чтобы получить первый момент дня:
withTimeAtStartOfDay()
. Аналогично в java.timeLocalDate::atStartOfDay
.Поищите в StackOverflow «joda half-open», чтобы увидеть больше обсуждений и примеров.
См. Этот пост Билла Шнайдера « Временные интервалы и другие диапазоны должны быть полуоткрытыми ».
Избегайте устаревших классов даты и времени
Классы java.util.Date и .Calendar, как известно, проблематичны. Избежать их.
Используйте классы java.time . Java.time структура является официальным преемником весьма успешной Joda-Time библиотеки.
java.time
Фреймворк java.time встроен в Java 8 и новее. Обратно перенесен на Java 6 и 7 в проекте ThreeTen-Backport , а затем адаптирован для Android в проекте ThreeTenABP .
An
Instant
- это момент на временной шкале в формате UTC с разрешением наносекунды .Примените часовой пояс, чтобы узнать время на настенных часах для некоторой местности.
Чтобы получить первое мгновение дня, просмотрите
LocalDate
класс и егоatStartOfDay
метод.Используя подход Half-Open, получите первый момент следующего дня.
В настоящее время в структуре java.time отсутствует
Interval
класс, описанный ниже для Joda-Time. Однако проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является испытательной площадкой для возможных будущих дополнений к java.time. Среди его классов естьInterval
. СоздайтеInterval
, передав паруInstant
объектов. Мы можем извлечьInstant
из нашихZonedDateTime
объектов.О java.time
Java.time каркас встроен в Java 8 и более поздних версий. Эти классы вытеснять неприятные старые устаревшие классы даты и времени , такие как
java.util.Date
,Calendar
, иSimpleDateFormat
.Чтобы узнать больше, см. Oracle Tutorial . И поищите в Stack Overflow множество примеров и объяснений. Спецификация - JSR 310 .
Проект Joda-Time , находящийся сейчас в режиме обслуживания , рекомендует перейти на классы java.time .
Вы можете обмениваться объектами java.time напрямую с вашей базой данных. Используйте драйвер JDBC, совместимый с JDBC 4.2 или новее. Нет необходимости в строках, нет необходимости в
java.sql.*
занятиях. Hibernate 5 и JPA 2.2 поддерживают java.time .Где взять классы java.time?
Joda времени
ОБНОВЛЕНИЕ: проект Joda-Time сейчас находится в режиме обслуживания и советует перейти на классы java.time . Я оставляю этот раздел нетронутым для истории.
Joda время имеет три класса для представления промежуток времени различных способов:
Interval
,Period
иDuration
. У AnInterval
есть определенное начало и конец на временной шкале Вселенной. Это соответствует нашей потребности в представлении «дня».Мы вызываем метод,
withTimeAtStartOfDay
а не устанавливаем время суток на нули. Из-за летнего времени и других аномалий первого момента дня может не быть00:00:00
.Пример кода с использованием Joda-Time 2.3.
При необходимости вы можете преобразовать его в файл java.util.Date.
источник
LocalDateTime
Java 8
Обновление : я добавил эти 2 метода в свои классы утилит Java здесь
Он находится в центральном репозитории Maven по адресу:
Java 7 и более ранние версии
С помощью Apache Commons
Без Apache Commons
источник
getStartOfDay
должно быть:LocalDateTime startOfDay = localDateTime.with(LocalTime.MIN);
т.е. LocalTime, а не LocalDateTime.getEndOfDay(Date date)
.getStartOfDay(Date date)
методы в разделе Java 8 верны, а именно LocalDateTime.MAX и .MIN помещают вас в самые ранние возможные даты в прошлом и будущем, а не в начале и конце дня. Вместо этого я бы предложил .atStartOfDay () для начала и .plusDays (1) .atStartOfDay (). MinusNanos (1) для завершения.localDateTimeToDate(LocalDateTime startOfDay)
выдает исключение - java.lang.IllegalArgumentException: java.lang.ArithmeticException: long overflowв getEndOfDay вы можете добавить:
Хотя с математической точки зрения, вы не можете указать конец дня, кроме как «до начала следующего дня».
Таким образом , вместо того , чтобы говорить,
if(date >= getStartOfDay(today) && date <= getEndOfDay(today))
вы должны сказать:if(date >= getStartOfDay(today) && date < getStartOfDay(tomorrow))
. Это гораздо более надежное определение (и вам не нужно беспокоиться о точности в миллисекундах).источник
java.time
Использование
java.time
фреймворка, встроенного в Java 8.источник
Local…
классов нет понятия часовых поясов и поправок на аномалии. Например, в некоторых часовых поясах переход на летнее время происходит в полночь, поэтому первый момент дня приходится на время01:00:00.0
(1 час ночи), а не на00:00:00.0
значение, созданное этим кодом.ZonedDateTime
Вместо этого используйте .Дополнительный способ найти начало дня с помощью java8 java.time.ZonedDateTime вместо прохождения
LocalDateTime
- это просто усечение входного ZonedDateTime до DAYS:источник
Для java 8 работают следующие однострочные операторы. В этом примере я использую часовой пояс UTC. Пожалуйста, подумайте об изменении часового пояса, который вы в настоящее время используете.
Если нет разницы во времени с выходом. Пытаться:
ZoneOffset.ofHours(0)
источник
toInstant
недопустимый синтаксис и концептуально избыточна.Java 8 или ThreeTenABP
ZonedDateTime
LocalDateTime
Надеюсь, это кому-то поможет.
источник
Я пробовал этот код, и он хорошо работает!
источник
ZonedDateTime
иInstant
в вашем распоряжении нет необходимости использоватьjava.sql.Timestamp
. Этот класс - один из ужасных старых устаревших классов, которые теперь вытесняются классами java.time . Начиная с JDBC 4.2, мы можем напрямую обмениваться объектами java.time с базой данных. Ваше смешение устаревших и современных классов не имеет для меня смысла.Еще одно решение, не зависящее от какой-либо структуры:
Обратите внимание, что он возвращает время в формате UTC.
источник
calendar.setTimeInMillis (0); дает точность до миллисекунд
источник
Я знаю, что это немного поздно, но в случае Java 8, если вы используете OffsetDateTime (который предлагает множество преимуществ, таких как TimeZone, Nanoseconds и т. Д.), Вы можете использовать следующий код:
источник
У меня было несколько неудобств со всеми решениями, потому что мне нужен был тип переменной Instant, а часовой пояс всегда мешал менять все, а затем, комбинируя решения, я увидел, что это хороший вариант.
и мы в результате
Я надеюсь это поможет тебе
источник
Instant
Interval
Думаю, проще всего было бы что-то вроде:
Эти миллисекунды можно затем преобразовать в Calendar, Instant или LocalDate в соответствии с вашими требованиями с помощью Joda Time.
источник
источник