Как создать объект 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. Тем не менее, классы, похоже, включают информацию о часовом поясе, которая кажется не только расточительной, но и подверженной ошибкам кодирования.
Ответ 11
Apache Commons Lang
DateUtils.isSameDay(date1, date2)
http://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/time/DateUtils.html#isSameDay(java.util.Date, java.util.Date)
Ответ 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 и наоборот упрощенное преобразование?