Как создать объект Java Date полночь сегодня и полночь завтра?
В моем коде мне нужно найти все мои вещи, которые произошли сегодня. Поэтому мне нужно сравнить даты с сегодняшнего дня в 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();
20 ответов
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);
Начиная с версии 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.
Для полноты картины, если вы используете Java 8, вы также можете использовать truncatedTo
метод Instant
класс, чтобы получить полночь в UTC.
Instant.now().truncatedTo(ChronoUnit.DAYS);
Как написано в Javadoc
Например, усечение с помощью модуля MINUTES будет округляться до ближайшей минуты, устанавливая секунды и наносекунды в ноль.
Надеюсь, поможет.
Самый простой способ найти полночь:
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);
Помните, 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
за кулисами...
Эти методы помогут вам
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();
}
Другие ответы верны, особенно ответ java.time от arganzheng. Как уже упоминалось, вам следует избегать старых классов java.util.Date/.Calendar, поскольку они плохо спроектированы, сбивают с толку и создают проблемы. Они были вытеснены классами java.time.
Позвольте мне добавить примечания о стратегии обработки полуночи и промежутков времени.
Полуоткрытый
В работе с датой и временем промежутки времени часто определяются с использованием подхода "полуоткрытого". В этом подходе начало включительно, а окончание - исключительно. Это решает проблемы и, если используется последовательно, значительно упрощает рассуждения о вашей дате и времени.
Одна решенная проблема - определение конца дня. Это последний момент дня 23:59:59.999
( миллисекунды)? Возможно, в классе java.util.Date (с самой ранней Java; хлопотно - избегайте этого класса!) И в очень успешной библиотеке Joda-Time. Но в других программах, таких как база данных, как Postgres, последний момент будет 23:59:59.999999
( микросекунды). Но в других программах, таких как инфраструктура java.time (встроенная в Java 8 и более поздние версии, преемник Joda-Time) и в некоторых базах данных, таких как база данных H2, последний момент может быть 23:59.59.999999999
( наносекунды). Вместо того, чтобы раскалывать волосы, думайте только в первый момент, а не в последний момент.
В Half-Open день начинается с первого момента одного дня и идет вверх, но не включает первый момент следующего дня. Так что вместо того, чтобы думать так:
… С сегодняшнего дня в 00:00 (полночь рано этим утром) до 12:00 (полночь сегодня вечером).
... думать так...
с первого момента сегодняшнего дня, но не включая первый момент завтрашнего дня:
(> =00:00:00.0
сегодня И <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() );
JDK8 - способ модуля времени Java:
LocalDateTime todayMidnight = LocalDate.now().atStartOfDay();
Также работают:
LocalDateTime todayMidnight = LocalDateTime.now().with(LocalTime.MIDNIGHT);
Начиная с JodaTime 2.3, toDateMidnight()
устарела.
Амортизация с 2.2 ---------------------- - DateMidnight [#41] Этот класс имеет недостатки в концепции Время полуночи иногда не происходит в некоторых часовых поясах Это результат перехода на летнее время с 00:00 до 01:00. DateMidnight - это, по сути, DateTime, время которого привязано к полуночи Такая концепция, как правило, является плохой для использования, учитывая LocalDate Замените DateMidnight на LocalDate Или замените его на DateTime, возможно, используя метод withTimeAtStartOfDay()
Вот пример кода без toDateMidnight()
метод.
Код
DateTime todayAtMidnight = new DateTime().withTimeAtStartOfDay();
System.out.println(todayAtMidnight.toString("yyyy-MM-dd HH:mm:ss"));
Выход (может отличаться в зависимости от вашего местного часового пояса)
2013-09-28 00:00:00
java.time
Если вы используете Java 8 и более поздние версии, вы можете попробовать пакет java.time ( Tutorial):
LocalDate tomorrow = LocalDate.now().plusDays(1);
Date endDate = Date.from(tomorrow.atStartOfDay(ZoneId.systemDefault()).toInstant());
Похоже, это вариант:
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 часов будет недостаточно (см. /questions/38404103/kak-ya-mogu-uvelichit-datu-na-odin-den-v-java/38404123#38404123 и другие ответы).
Используя Apache Commons..
//For midnight today
Date today = new Date();
DateUtils.truncate(today, Calendar.DATE);
//For midnight tomorrow
Date tomorrow = DateUtils.addDays(today, 1);
DateUtils.truncate(tomorrow, Calendar.DATE);
Я сделал это иначе, чем все остальные здесь. Я новичок в 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. Тем не менее, классы содержат информацию о часовом поясе, которая кажется не только расточительной, но и подвержена ошибкам кодирования.
Почти как ответы раньше, но никто не упомянул параметр AM_PM:
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
cal.set(Calendar.AM_PM, Calendar.AM);
Из-за одного дня 24 * 60 * 60 * 1000
мс, полночь этого дня можно рассчитать как...
long now = System.currentTimeMillis();
long delta = now % 24 * 60 * 60 * 1000;
long midnight = now - delta;
Date midnightDate = new Date(midnight);`
Самый простой способ с JodaTime
DateMidnight date = DateMidnight.now();
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, java.util.Date)
Date now= new Date();
// Today midnight
Date todayMidnight = new Date(endTime.getTime() -endTime.getTime()%DateUtils.MILLIS_PER_DAY);
// tomorrow midnight
Date tomorrowMidnight = new Date(endTime.getTime() -endTime.getTime()%DateUtils.MILLIS_PER_DAY + DateUtils.MILLIS_PER_DAY);
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 и наоборот самое простое преобразование?
Старомодный способ..
private static Date getDateWithMidnight(){
long dateInMillis = new Date().getTime();
return new Date(dateInMillis - dateInMillis%(1000*60*60*24) - TimeZone.getDefault().getOffset(dateInMillis));
}
Я знаю, что это очень старый пост. Я думал поделиться своими знаниями здесь!
Для даты Середина ночи сегодня с точным часовым поясом вы можете использовать следующие
public static Date getCurrentDateWithMidnightTS(){
return new Date(System.currentTimeMillis() - (System.currentTimeMillis()%(1000*60*60*24)) - (1000*60 * 330));
}
куда (1000*60 * 330)
вычитается, т. е. фактически относится к часовому поясу, например, индийский часовой пояс, т. е. Калькутта отличается на +5:30 часов от фактического. Так вычитая это с преобразованием в миллисекунды.
Так что измените последнее вычтенное число согласно вам. Я создаю продукт, т. Е. Базируюсь только в Индии, поэтому просто использовал конкретную метку времени.