Информация о сокращении даты Java
У меня есть объект Java Date, содержащий информацию о дате и времени. Я хочу написать метод, который отсекает информацию о времени, усекает часы-минуты-секунды, поэтому у меня остается только дата.
Пример ввода:
2008-01-01 13:15:00
Ожидаемый результат:
2008-01-01 00:00:00
У вас есть совет? Я пытался сделать что-то вроде этого:
(timestamp / (24 * 60 * 60 * 1000)) * (24 * 60 * 60 * 1000)
но у меня возникли проблемы с часовым поясом.
Ответы
Ответ 1
Рекомендуемым способом обработки даты/времени является использование Calendar
:
Calendar cal = Calendar.getInstance(); // locale-specific
cal.setTime(dateObject);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
long time = cal.getTimeInMillis();
Ответ 2
Вы просмотрели метод DateUtils в Apache Commons Lang?
Date truncatedDate = DateUtils.truncate(new Date(), Calendar.DATE);
удалит элемент времени.
Ответ 3
Вы посмотрели Joda? Это намного проще и интуитивно понятным способом работы с датами и временем. Например, вы можете преобразовать тривиально между (скажем) LocalDateTime и LocalDate.
например. (для иллюстрации API)
LocalDate date = new LocalDateTime(milliseconds).toLocalDate()
Кроме того, он решает некоторые проблемы безопасности потоков с помощью форматировщиков даты и времени и настоятельно рекомендуется работать с любыми проблемами даты и времени на Java.
Ответ 4
Просто быстрое обновление в свете классов java.time, теперь встроенных в Java 8 и более поздние версии.
LocalDateTime
имеет метод truncatedTo
, который эффективно решает то, о чем вы здесь говорите:
LocalDateTime.now().truncatedTo(ChronoUnit.MINUTES)
Это время будет отображаться только в минутах:
2015-03-05T11:47
Вы можете использовать ChronoUnit
(или TemporalUnit
) меньше DAYS для выполнения усечения (поскольку усечение применяется только к временной части LocalDateTime, не до даты часть).
Ответ 5
Date date = new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
date = cal.getTime();
Ответ 6
С помощью Joda вы можете легко получить ожидаемую дату.
Начиная с версии 2.7 (возможно, начиная с некоторой предыдущей версии, большей, чем 2,2), как отмечает комментатор, toDateMidnight
устарел в пользу или метко названный withTimeAtStartOfDay()
, сделав удобный
DateTime.now().withTimeAtStartOfDay()
возможно.
Добавлен способ более удобного API.
В более старых версиях вы можете сделать
new DateTime(new Date()).toDateMidnight().toDate()
Ответ 7
Для временных меток:
timestamp -= timestamp % (24 * 60 * 60 * 1000)
Ответ 8
Используйте DateUtils из Apache с усечением, например:
DateUtils.truncate(Calendar.getInstance().getTime(), Calendar.DATE);
Ответ 9
Я сделал усечение с новым API java8. Я столкнулся с одной странной вещью, но в целом она усекается...
Instant instant = date.toInstant();
instant = instant.truncatedTo(ChronoUnit.DAYS);
date = Date.from(instant);
Ответ 10
Из java.util.Date JavaDocs:
Класс Date представляет определенный момент времени с точностью до миллисекунды
и из java.sql.Date JavaDocs:
Чтобы соответствовать определению SQL DATE, значения миллисекунды, обернутые экземпляром java.sql.Date, должны быть "нормализованы", установив часы, минуты, секунды и миллисекунды на ноль в конкретном часовом поясе, с которым экземпляр связан.
Итак, лучший подход - использовать java.sql.Date, если вам не нужна временная часть
java.util.Date utilDate = new java.util.Date();
java.sql.Date sqlDate = new java.sql.Date(System.currentTimeMillis());
а выход:
java.util.Date : Thu Apr 26 16:22:53 PST 2012
java.sql.Date : 2012-04-26
Ответ 11
ТЛ; др
LocalDateTime.parse( // Lacking an offset or time zone, parse as a 'LocalDateTime'. *Not* a specific moment in time.
"2008-01-01 13:15:00".replace( " " , "T" ) // Alter input string to comply with ISO 8601 standard format.
)
.toLocalDate() // Extract a date-only value.
.atStartOfDay( // Do not assume the day starts at 00:00:00. Let class determine start-of-day.
ZoneId.of( "Europe/Paris" ) // Determining a specific start-of-day requires a time zone.
) // Result is a 'ZonedDateTime' object. At this point we have a specific moment in time, a point on the timeline.
.toString() // Generate a String in standard ISO 8601 format, wisely extended to append the name of the time zone in square brackets.
2008-01-01T00:00+01:00[Europe/Paris]
Чтобы сгенерировать строку в нужном формате, передайте DateTimeFormatter
.
LocalDateTime.parse( // Lacking an offset or time zone, parse as a 'LocalDateTime'. *Not* a specific moment in time.
"2008-01-01 13:15:00".replace( " " , "T" ) // Alter input string to comply with ISO 8601 standard format.
)
.toLocalDate() // Extract a date-only value.
.atStartOfDay( // Do not assume the day starts at 00:00:00. Let class determine start-of-day.
ZoneId.of( "Europe/Paris" ) // Determining a specific start-of-day requires a time zone.
) // Result is a 'ZonedDateTime' object. At this point we have a specific moment in time, a point on the timeline.
.format( // Generate a String representing the objects value.
DateTimeFormatter.ISO_LOCAL_DATE_TIME // Built-in predefined formatter close to what you want.
)
.replace( "T" , " " ) // Replace the standards use of a 'T' in the middle with your desired SPACE character.
2008-01-01 00:00:00
Подробнее
Другие ответы верны, но используют старые классы даты и времени, которые теперь устарели в среде java.time.
java.time
Инфраструктура java.time встроена в Java 8 и более поздние версии. Большая часть функциональности java.time перенесена на Java 6 & 7 (ThreeTen-Backport) и дополнительно адаптированы для Android (ThreeTenABP).
Сначала измените входную строку, чтобы она соответствовала канонической версии формата ISO 8601. Стандартные форматы ISO 8601 по умолчанию используются в классах java.time для анализа/генерации строк, представляющих значения даты и времени. Нам нужно заменить это пространство в середине на T
.
String input = "2008-01-01 13:15:00".replace( " " , "T" ); // → 2008-01-01T13:15:00
Теперь мы можем проанализировать его как LocalDateTime
, где "Местный" означает отсутствие определенной местности. На входе отсутствует смещение от UTC или информация о часовом поясе.
LocalDateTime ldt = LocalDateTime.parse( input );
ldt.toString()… 2008-01-01T13:15:00
Если вас не волнует ни время суток, ни часовой пояс, перейдите в LocalDate
.
LocalDate ld = ldt.toLocalDate();
ld.toString()… 2008-01-01
Первый момент дня
Если вместо этого вы хотите установить время дня в первый момент дня, используйте класс ZonedDateTime
, а затем преобразуйте его в объект LocalDate
, чтобы вызвать его atStartOfDay
метод. Помните, что первым моментом может быть не время 00:00:00
из-за перехода на летнее время или, возможно, по другим причинам.
Часовой пояс имеет решающее значение, потому что в любой данный момент дата меняется по всему миру в зависимости от зоны. Например, несколько минут после полуночи в Париже - новый день для парижан, но для канадцев "вчера" в Монреале по-прежнему.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ldt.atZone( zoneId );
LocalDate ldFromZdt = zdt.toLocalDate();
ZonedDateTime zdtStartOfDay = ldFromZdt.atStartOfDay( zoneId );
zdtStartOfDay.toString()… 2008-01-01T00:00:00-05:00[America/Montreal]
UTC
Чтобы увидеть этот момент через объектив часового пояса UTC, извлеките объект Instant
. И ZonedDateTime
, и Instant
будут представлять один и тот же момент на временной шкале, но будут отображаться как два разных времени настенных часов.
Instant
является базовым классом строительных блоков в java.time, всегда в UTC по определению. Используйте этот класс часто, как вы обычно делаете бизнес-логику, хранение данных и обмен данными в UTC.
Instant instant = zdtStartOfDay.toInstant();
instant.toString()… 2008-01-01T05:00:00Z
Мы видим 5 утра, а не полночь. В стандартном формате Z
на конце является сокращением от Zulu
и означает "UTC".
О java.time
Среда java.time встроена в Java 8 и более поздние версии. Эти классы вытесняют проблемные старые устаревшие классы даты и времени, такие как java.util.Date
, Calendar
и & SimpleDateFormat
.
Проект Joda-Time, который теперь находится в режиме обслуживания, рекомендует выполнить переход на классы java.time.
Чтобы узнать больше, см. Учебное пособие по Oracle. И поищите в Кару множество примеров и объяснений. Спецификация: JSR 310.
Вы можете обмениваться объектами java.time напрямую с вашей базой данных. Используйте драйвер JDBC, совместимый с JDBC 4.2 или более поздней версией. Нет необходимости в строках, нет необходимости в классах java.sql.*
.
Где взять классы java.time?
Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Здесь вы можете найти несколько полезных классов, таких как Interval
, YearWeek
, YearQuarter
и еще more.
Ответ 12
Используйте метод Calendar class set()
, чтобы установить поля HOUR_OF_DAY, MINUTE, SECOND
и MILLISECOND
в ноль.
Ответ 13
Просто clear()
избыточные поля.
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.clear(Calendar.MINUTE);
calendar.clear(Calendar.SECOND);
calendar.clear(Calendar.MILLISECOND);
Date truncatedDate = calendar.getTime();
Из Java 8 лучше использовать метод truncatedTo
из LocalDateTime
, например:
LocalDateTime.now().truncatedTo(ChronoUnit.DAYS)
Ответ 14
Вопрос противоречив. Он запрашивает дату без времени суток, но отображает пример со временем 00:00:00
.
Joda времени
UPDATE: Проект Joda-Time теперь находится в режим обслуживания, команда советует перейти на классы java.time. См. мой другой ответ для решения java.time.
Если вместо этого вы хотите установить время дня в первый момент дня, используйте объект DateTime
на Joda-Time, и вызовите метод withTimeAtStartOfDay
. Имейте в виду, что первым моментом может быть не время 00:00:00
из-за летнего времени или, возможно, других аномалий.
Ответ 15
Меня действительно раздражало, что новый "улучшенный" конструктор календаря не принимает int за миллисекунды, как "ужасная" старая дата.
Затем я получил действительно крест и написал это:
long stuffYou = startTime.getTimeInMillis() % 1000;
startTime.setTimeInMillis(startTime.getTimeInMillis() - stuffYou);
В то время я не использовал слово "материал", но
тогда я обнаружил счастье этого:
startTime.set(Calendar.MILLISECOND, 0);
Но я все еще довольно смущен.
Ответ 16
Вы можете сделать это, чтобы избежать проблемы с часовым поясом:
public static Date truncDate(Date date) {
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
cal.setTime(date);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
return cal.getTime();
}
Хотя объект Java Date
является значением метки времени, но во время усечения он будет преобразован в локальный часовой пояс, поэтому вы получите неожиданное значение, если ожидаете значение из часового пояса UTC.
Ответ 17
Может быть, поздний ответ, но вот способ сделать это в одной строке без использования каких-либо библиотек:
new SimpleDateFormat("yyyy-MM-dd").parse(new SimpleDateFormat("yyyy-MM-dd").format(YOUR_TIMESTAMP))
Ответ 18
С Joda-Time начиная с версии 2.0 вы можете использовать LocalDate.toDate()
.
Просто
// someDatetime is whatever java.util.Date you have.
Date someDay = new LocalDate(someDatetime).toDate();
Ответ 19
Для всех ответов, использующих Calendar, вы должны использовать его так:
public static Date truncateDate(Date date) {
Calendar c = Calendar.getInstance();
c.setTime(date);
c.set(Calendar.HOUR_OF_DAY, c.getActualMinimum(Calendar.HOUR_OF_DAY));
c.set(Calendar.MINUTE, c.getActualMinimum(Calendar.MINUTE));
c.set(Calendar.SECOND, c.getActualMinimum(Calendar.SECOND));
c.set(Calendar.MILLISECOND, c.getActualMinimum(Calendar.MILLISECOND));
return c.getTime();
}
Но я предпочитаю это:
public static Date truncateDate(Date date) {
return new java.sql.Date(date.getTime());
}
Ответ 20
Я исправил проблему следующим образом (в восточной восьмой зоне (по пекинскому времени)):
private Date getTruncatedDate(Date d) {
if (d == null) {
return null;
}
long h = 60 * 60 * 1000L;
long dateStamp = d.getTime() - (d.getTime() + 8 * h) % (24 * h);
return new Date(dateStamp);
}
Прежде всего, вам должно быть понятно, что такое timestamp.
Отметка времени - это общее количество миллисекунд с 01 января 00:00:00 1970 года по Гринвичу (аналогично UTC) или с четверга января 01:00:00 по Гринвичу 1970 года по настоящее время.
Помните: timestamp не зависит от часового пояса.
Таким образом, вы получите тот же результат со следующим утверждением в разных часовых поясах:
System.out.println(new Date().getTime());
и
System.out.println(new Date(0));
печатает разную информацию о времени в разных часовых поясах:
Если вы установите часовой пояс вашего компьютера как UTC, вы получите
Thu Jan 01 00:00:00 UTC 1970
Но если вы установите часовой пояс (UTC +8: 00) Пекин, Чунцин, Гонконг, Урумк, вы получите:
Thu Jan 01 08:00:00 CST 1970
Java получает отметку времени, затем отображает информацию о дате и времени в соответствии с часовым поясом.
Для ознакомления с тем, как Java отображает информацию о дате и времени в разных часовых поясах, легко выполнить преобразование информации о времени. Вы должны получить отметку времени и принять во внимание часовой пояс при отключении информации о времени. Затем вы можете создать новый объект Date с отметкой времени вырезания (мы можем назвать его отметкой даты), java будет компенсировать часовой пояс при отображении информации о дате.
Как и в восточной восьмой зоне (по пекинскому времени), пекинское время раньше на 8 часов, чем по Гринвичу, поэтому при выполнении операции по модулю вы должны вычесть больше 8 часов.
То есть сначала вы должны получить время по Гринвичу, а затем Java добавит 8 часов при отображении времени на основе настроек часового пояса вашего компьютера.
Вопрос с часовым поясом неясен, и он меня долго озадачивает. Теперь я проясню.
Надежда помогает.
2018-01-04
Метод ниже также работает.
private Date getTruncatedDate2(Date d) {
Calendar cal = Calendar.getInstance(); // locale-specific
cal.setTime(d);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
return cal.getTime();
}
Ответ 21
Вот простой способ получить дату без времени, если вы используете Java 8+: используйте тип java.time.LocalDate вместо даты.
LocalDate now = LocalDate.now();
System.out.println(now.toString());
Вывод:
2019-05-30
https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html