Как создать объект Java Date в полночь сегодня и в полночь завтра?

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

Я знаю...

Date today = new Date(); 

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

Date beginning = new Date(0);

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

UPDATE; Я сделал это, но, конечно, есть более простой способ?

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();

Ответ 1

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 времени

Если вы используете JDK < 8, я рекомендую Joda Time, потому что API действительно хорош:

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

удаp >

Так как версия 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.

Ответ 2

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

Calendar c = new GregorianCalendar();

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

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

c.add(Calendar.DAY_OF_MONTH, 1);

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

UPDATE: Однако мой любимый способ справиться с этой проблемой - использовать DateUtils класс из Commons Lang:

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

Он использует Calendar за кулисами...

Ответ 3

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

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);

Ответ 4

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

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

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

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

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

Ответ 5

Начиная с версии 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

java.time

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

LocalDate tomorrow = LocalDate.now().plusDays(1);
Date endDate = Date.from(tomorrow.atStartOfDay(ZoneId.systemDefault()).toInstant());

Ответ 7

Это выглядит как опция:

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 часа, чтобы этого было недостаточно (см. fooobar.com/questions/16119/... и другие его ответы).

Ответ 8

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

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

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

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

Half-Open

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

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

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

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

... подумайте вот так...

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

В работе с базой данных этот подход означает не использование BETWEEN operator в 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() );

Ответ 10

Я сделал это иначе, чем все остальные. Я новичок в 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? Я бы подумал, что Timezones нужно использовать только при использовании с i/o, но внутренне всегда нужно использовать в UTC. Тем не менее, классы, похоже, включают информацию о часовом поясе, которая кажется не только расточительной, но и подверженной ошибкам кодирования.

Ответ 12

Самый простой способ с JodaTime

DateMidnight date = DateMidnight.now();

Ответ 13

Из-за одного дня 24 * 60 * 60 * 1000 ms, полночь этого дня можно рассчитать как...

long now = System.currentTimeMillis();
long delta = now % 24 * 60 * 60 * 1000;
long midnight = now - delta;
Date midnightDate = new Date(midnight);`

Ответ 14

Я знаю, что это очень старый пост. Я думал поделиться своими знаниями здесь!

На сегодняшний день Mid Night сегодня с точным часовым поясом вы можете использовать следующие

public static Date getCurrentDateWithMidnightTS(){

    return new Date(System.currentTimeMillis() - (System.currentTimeMillis()%(1000*60*60*24)) - (1000*60 * 330));
}

Где (1000*60 * 330) вычитается, то есть фактически связано с часовым поясом, например, с индийским часовым поясом, то есть kolkata отличается от +5: 30 часов от фактического. Итак, вычитаем это с преобразованием в миллисекунды.

Итак, измените последнее вычитаемое число в соответствии с вами. Я создаю продукт, то есть только в Индии. Так что просто используется конкретная метка времени.

Ответ 15

Date todayMidnightUTC = java.sql.Date.valueOf(LocalDate.now());
Date tomorrowMidnightUTC = java.sql.Date.valueOf(LocalDate.now().plusDays(1));
Date anyMidnightLocal = java.sql.Date.valueOf(LocalDate.from(dateTime.toInstant().atZone(ZoneId.systemDefault())));

Но будьте осторожны, что java.sql.Date.toInstant() всегда выбрасывает UnsupportedOperationException.

Через LocalDate в java.util.Date и наоборот упрощенное преобразование?