Как создать объект Java Date полночь сегодня и полночь завтра? - PullRequest
166 голосов
/ 28 июля 2011

В моем коде мне нужно найти все мои вещи, которые произошли сегодня.Поэтому мне нужно сравнить даты с сегодняшнего дня в 00:00 (полночь рано утром) до 12:00 (полночь сегодня вечером).

Я знаю ...

Date today = new Date(); 

..Получи меня прямо сейчас.И ...

Date beginning = new Date(0);

... дает мне нулевое время 1 января 1970 года. Но как проще получить нулевое время сегодня и нулевое время завтра?

ОБНОВЛЕНИЕ;Я сделал это, но наверняка есть более простой способ?

Calendar calStart = new GregorianCalendar();
calStart.setTime(new Date());
calStart.set(Calendar.HOUR_OF_DAY, 0);
calStart.set(Calendar.MINUTE, 0);
calStart.set(Calendar.SECOND, 0);
calStart.set(Calendar.MILLISECOND, 0);
Date midnightYesterday = calStart.getTime();

Calendar calEnd = new GregorianCalendar();
calEnd.setTime(new Date());
calEnd.set(Calendar.DAY_OF_YEAR, calEnd.get(Calendar.DAY_OF_YEAR)+1);
calEnd.set(Calendar.HOUR_OF_DAY, 0);
calEnd.set(Calendar.MINUTE, 0);
calEnd.set(Calendar.SECOND, 0);
calEnd.set(Calendar.MILLISECOND, 0);
Date midnightTonight = calEnd.getTime();

Ответы [ 19 ]

319 голосов
/ 28 июля 2011

java.util.Calendar

// today    
Calendar date = new GregorianCalendar();
// reset hour, minutes, seconds and millis
date.set(Calendar.HOUR_OF_DAY, 0);
date.set(Calendar.MINUTE, 0);
date.set(Calendar.SECOND, 0);
date.set(Calendar.MILLISECOND, 0);

// next day
date.add(Calendar.DAY_OF_MONTH, 1);

JDK 8 - java.time.LocalTime и java.time.LocalDate

LocalTime midnight = LocalTime.MIDNIGHT;
LocalDate today = LocalDate.now(ZoneId.of("Europe/Berlin"));
LocalDateTime todayMidnight = LocalDateTime.of(today, midnight);
LocalDateTime tomorrowMidnight = todayMidnight.plusDays(1);

Joda-Time

Если вы используете JDK <8, я рекомендую <a href="http://www.joda.org/joda-time/" rel="noreferrer"> Joda Time , потому что API действительно хорош:

DateTime date = new DateTime().toDateMidnight().toDateTime();
DateTime tomorrow = date.plusDays(1);

Начиная с версии 2.3 Joda Time DateMidnight устарела , поэтому используйте это:

DateTime today = new DateTime().withTimeAtStartOfDay();
DateTime tomorrow = today.plusDays(1).withTimeAtStartOfDay();

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

DateTimeZone timeZone = DateTimeZone.forID("America/Montreal");
DateTime today = new DateTime(timeZone).withTimeAtStartOfDay(); // Pass time zone to constructor.
32 голосов
/ 07 сентября 2012

Самый простой способ найти полночь:

Long time = new Date().getTime();
Date date = new Date(time - time % (24 * 60 * 60 * 1000));

На следующий день:

Date date = new Date(date.getTime() + 24 * 60 * 60 * 1000);
30 голосов
/ 07 ноября 2016

Для полноты картины, если вы используете Java 8 , вы также можете использовать метод truncatedTo класса Instant, чтобы получить полночь в UTC .

Instant.now().truncatedTo(ChronoUnit.DAYS);

Как написано в Javadoc

Например, усечение с помощью модуля МИНУТ будет округляться до ближайшей минуты, устанавливая секунды и наносекунды на ноль.

Надеюсь, это поможет.

28 голосов
/ 28 июля 2011

Помните, Date не используется для представления дат (!).Для представления даты вам нужен календарь.Это:

Calendar c = new GregorianCalendar();

создаст экземпляр Calendar, представляющий текущую дату в вашем текущем часовом поясе.Теперь вам нужно обрезать каждое поле ниже дня (час, минута, секунда и миллисекунда), установив для него значение 0.Сегодня у вас полночь.

Теперь, чтобы получить полночь следующего дня, вам нужно добавить один день:

c.add(Calendar.DAY_OF_MONTH, 1);

Обратите внимание, что добавление 86400 секунд или 24 часов некорректно из-залетнее время, которое может произойти в это время.

ОБНОВЛЕНИЕ: Однако мой любимый способ решения этой проблемы - использовать DateUtils класс из Commons Lang :

Date start = DateUtils.truncate(new Date(), Calendar.DAY_OF_MONTH))
Date end = DateUtils.addDays(start, 1);

Используется Calendar за кадром ...

13 голосов
/ 09 декабря 2015

эти методы вам помогут -

public static Date getStartOfDay(Date date) {
     Calendar calendar = Calendar.getInstance();
     calendar.setTime(date);
     calendar.set(Calendar.HOUR_OF_DAY, 0);
     calendar.set(Calendar.MINUTE, 0);
     calendar.set(Calendar.SECOND, 0);
     calendar.set(Calendar.MILLISECOND, 0);
     return calendar.getTime();
 }

и

public static Date getEndOfDay(Date date) {
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(date);
    calendar.set(Calendar.HOUR_OF_DAY, 23);
    calendar.set(Calendar.MINUTE, 59);
    calendar.set(Calendar.SECOND, 59);
    calendar.set(Calendar.MILLISECOND, 999);
    return calendar.getTime();
}
9 голосов
/ 27 сентября 2013

Начиная с JodaTime 2.3, toDateMidnight() устарел.

С Обновление с 2.2 до 2.3

    Deprecations since 2.2
    ----------------------
    - DateMidnight [#41]
     This class is flawed in concept
     The time of midnight occasionally does not occur in some time-zones
     This is a result of a daylight savings time from 00:00 to 01:00
     DateMidnight is essentially a DateTime with a time locked to midnight
     Such a concept is more generally a poor one to use, given LocalDate
     Replace DateMidnight with LocalDate
     Or replace it with DateTime, perhaps using the withTimeAtStartOfDay() method

Вот пример кода без toDateMidnight() метода.

Код

DateTime todayAtMidnight = new DateTime().withTimeAtStartOfDay();
System.out.println(todayAtMidnight.toString("yyyy-MM-dd HH:mm:ss"));

Вывод ( может отличаться в зависимости от вашего часового пояса )

2013-09-28 00:00:00
6 голосов
/ 10 августа 2015

java.time

Если вы используете Java 8 и новее, вы можете попробовать java.time пакет ( Tutorial ):

LocalDate tomorrow = LocalDate.now().plusDays(1);
Date endDate = Date.from(tomorrow.atStartOfDay(ZoneId.systemDefault()).toInstant());
6 голосов
/ 22 апреля 2016

Другие ответы верны, особенно ответ java.time от arganzheng .Как уже упоминалось, вам следует избегать старых классов java.util.Date/.Calendar, поскольку они плохо спроектированы, сбивают с толку и создают проблемы.Они были вытеснены классами java.time.

Позвольте мне добавить примечания о стратегии вокруг обработки в полночь и промежутков времени .

Half-Открыто

В работе с датой и временем промежутки времени часто определяются с использованием подхода «полуоткрытого».В этом подходе начало включительно , а окончание исключительно .Это решает проблемы и, если используется последовательно, значительно упрощает рассуждения об обработке даты и времени.

Одна из решенных проблем - определение конца дня.Последний момент дня 23:59:59.999 ( миллисекунды )?Возможно, в классе java.util.Date (с самой ранней Java; хлопотно - избегайте этого класса!) И в очень успешной библиотеке Joda-Time .Но в других программах, таких как базы данных, такие как Postgres, последний момент будет 23:59:59.999999 ( микросекунд ).Но в других программах, таких как java.time framework (встроенный в Java 8 и новее, преемник Joda-Time), и в некоторых базах данных, таких как H2 Database , последний момент можетбыть 23:59.59.999999999 ( наносекунд ).Вместо того, чтобы расщеплять волосы, думайте только в первый момент, а не в последний момент.

В Half-Open день начинается с первого момента одного дня и идет до, но не включает первый момент следующего дня.Поэтому вместо того, чтобы думать так:

… с сегодняшнего дня в 00:00 (полночь рано утром) до 12:00 (полночь сегодня вечером).

… думайте какэто…

с первого момента сегодняшнего дня, но не включая первый момент завтрашнего дня:(> = 00:00:00.0 сегодня И <<code>00:00:00.0 завтра)

В работе с базой данных этот подход означает не с использованием оператора BETWEEN вSQL.

начало дня

Кроме того, первый момент дня - , а не , всегда время суток 00:00:00.0. Переход на летнее время (DST) в некоторых часовых поясах и, возможно, в других аномалиях, может означать, что день начинается в другое время.

Итак, пусть классы java.time определят начало дня с помощью вызова LocalDate::atStartOfDay( ZoneId ).Таким образом, мы должны объехать LocalDate и вернуться к ZonedDateTime, как вы можете видеть в этом примере кода.

ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now( zoneId );
ZonedDateTime todayStart = now.toLocalDate().atStartOfDay( zoneId );
ZonedDateTime tomorrowStart = todayStart.plusDays( 1 );

Обратите внимание на прохождениенеобязательно ZoneId.Если этот параметр опущен, текущий часовой пояс JVM по умолчанию применяется неявно.Лучше быть явным.

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

Преобразование

Если вы должны использовать java.util.Date или .Calendarпоищите новые методы преобразования, добавленные в эти старые классы.

java.util.Date utilDate = java.util.Date.from( todayStart.toInstant() );
java.util.GregorianCalendar gregCal = java.util.GregorianCalendar.from( todayStart );

промежуток времени

Кстати, если вы много работаете с промежутками времени, взгляните на:

  • Duration
  • Period
  • IntervalКласс Interval находится в проекте ThreeTen-Extra , являющемся расширением фреймворка java.time.Этот проект является полигоном для возможных будущих дополнений к java.time.Interval todayMontreal = Interval.of( todayStart.toInstant() , tomorrowStart.toInstant() );

О java.time

Создан фреймворк java.time в Java 8 и позже.Эти классы вытесняют проблемные старые устаревшие классы даты и времени, такие как java.util.Date, Calendar и & SimpleDateFormat.

Проект Joda-Time , теперь в режиме обслуживания , рекомендует выполнить переход на классы java.time .

Чтобы узнатьподробнее см. Oracle Tutorial .И поиск переполнения стека для многих примеров и объяснений.Спецификация: JSR 310 .

Вы можете обмениваться java.time объектами напрямую с вашей базой данных.Используйте драйвер JDBC , совместимый с JDBC 4.2 или более поздней версии.Нет необходимости в строках, нет необходимости в java.sql.* классах.

Где получить классы java.time?

  • Java SE 8 , Java SE 9 , Java SE 10, Java SE 11 и более поздние версии - часть стандартного Java API с связанной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и JavaSE 7
    • Большинство функций java.time перенесены в Java 6 & 7 в ThreeTen-Backport .
  • Android
    • Более поздние версии пакетов Android для реализации java.time классы.
    • Для более ранних версий Android (<26) проект <a href="https://github.com/JakeWharton/ThreeTenABP" rel="nofollow noreferrer"> ThreeTenABP адаптируется ThreeTen-Backport (упомянуто выше).См. Как использовать ThreeTenABP… .

ThreeTen-Extra Проект расширяет java.time дополнительными классами.Этот проект является полигоном для возможных будущих дополнений к java.time.Вы можете найти здесь несколько полезных классов, таких как Interval, YearWeek, YearQuarter и more .

4 голосов
/ 18 августа 2014

Похоже, это вариант:

DateFormat justDay = new SimpleDateFormat("yyyyMMdd");
Date thisMorningMidnight = justDay.parse(justDay.format(new Date()));

, чтобы добавить к нему день, либо

Date tomorrow = new Date(thisMorningMidnight.getTime() + 24 * 60 * 60 * 1000);

или

Calendar c = Calendar.getInstance();
c.setTime(thisMorningMidnight);
c.add(Calendar.DATE, 1);
Date tomorrowFromCalendar = c.getTime();

У меня есть догадкапоследнее предпочтительнее в случае чего-то странного, например, перехода на летнее время, в результате которого добавления 24 часов будет недостаточно (см. https://stackoverflow.com/a/4336131/32453 и другие ответы).

2 голосов
/ 21 августа 2011

Я сделал это иначе, чем все остальные здесь. Я новичок в Java, так что, возможно, мое решение плохое.

Date now = new Date();
Date midnightToday = new Date(now.getYear(), now.getMonth(), now.getDate());

Я не уверен, что это работает, но в любом случае, я был бы признателен за любые отзывы об этом решении.

Я смущен приведенным выше утверждением, что вы можете рассчитать завтра, позвонив:

c.add(Calendar.DAY_OF_MONTH, 1);

Если вы добавите 1 к дню месяца, а это 31-й день, разве вы не получите 32-й день месяца?

Почему времена / даты не все основаны на UTC в Java? Я думаю, что часовые пояса должны быть необходимы только при использовании с I / O, но внутренне всегда должны использоваться в UTC. Однако классы, похоже, содержат информацию о часовом поясе, которая кажется не только расточительной, но и подвержена ошибкам кодирования.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...