Информация о дате отключения Java - PullRequest
104 голосов
/ 15 декабря 2009

У меня есть объект Java Date, содержащий информацию о дате и времени. Я хочу написать метод, который отсекает информацию о времени, усекает часы-минуты-секунды, поэтому у меня остается только дата.

Пример ввода:

2008-01-01 13:15:00

Ожидаемый результат:

2008-01-01 00:00:00

У вас есть совет? Я пытался сделать что-то вроде этого:

(timestamp / (24 * 60 * 60 * 1000)) * (24 * 60 * 60 * 1000)

но у меня возникли проблемы с часовым поясом.

Ответы [ 21 ]

3 голосов
/ 28 июня 2016

ТЛ; др

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 [Европа / Париж]

Чтобы сгенерировать строку в желаемом формате, передайте 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 object’s value.
    DateTimeFormatter.ISO_LOCAL_DATE_TIME       // Built-in predefined formatter close to what you want. 
)
.replace( "T" , " " )                           // Replace the standard’s 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 [Америка / Монреаль]

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 Tutorial . И поиск переполнения стека для многих примеров и объяснений. Спецификация JSR 310 .

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

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

  • Java SE 8 , Java SE 9 и выше
    • Встроенный.
    • Часть стандартного Java API со встроенной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и Java SE 7
    • Большая часть JAVФункциональность a.time перенесена в Java 6 & 7 в ThreeTen-Backport .
  • Android

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

2 голосов
/ 20 июня 2014

Вопрос противоречивый. Он запрашивает дату без времени суток, но отображает пример со временем 00:00:00.

Joda-Time

ОБНОВЛЕНИЕ: Проект Joda-Time теперь находится в режиме обслуживания , с командой, советующей перейти на java.time классы. См. мой другой ответ для решения java.time.

Если вместо этого вы хотите установить время дня в первый момент дня, используйте объект DateTime в библиотеке Joda-Time и вызовите его withTimeAtStartOfDay метод. Помните, что первым моментом может быть не время 00:00:00 из-за перехода на летнее время или из-за других аномалий.

2 голосов
/ 15 декабря 2009

Используйте метод set() класса Calendar , чтобы установить поля HOUR_OF_DAY, MINUTE, SECOND и MILLISECOND на ноль.

1 голос
/ 12 июня 2013

Всего 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();
1 голос
/ 19 сентября 2013

Меня действительно раздражало, что новый «улучшенный» конструктор календаря не принимает целое число в течение миллисекунд, как «ужасный» старый Date. Я тогда получил действительно крест и написал это:

long stuffYou = startTime.getTimeInMillis() % 1000;
startTime.setTimeInMillis(startTime.getTimeInMillis() - stuffYou);

В то время я не использовал слово «вещи», но тогда я обнаружил счастье этого:

startTime.set(Calendar.MILLISECOND, 0);

Но я все еще очень расстроен из-за этого.

1 голос
/ 13 марта 2018

Вы можете сделать это, чтобы избежать проблемы с часовым поясом:

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.

0 голосов
/ 30 мая 2019

Вот простой способ получить дату без времени, если вы используете 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

0 голосов
/ 27 декабря 2017

Я исправил проблему следующим образом (в восточной восьмой зоне (по пекинскому времени)):

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

Прежде всего, вам должно быть понятно, что такое отметка времени. Отметка времени - это общее количество миллисекунд с 01 января 00:00:00 1970 года по Гринвичу (аналогично UTC) или с четверга января 01:00:00 по Гринвичу 1970 года по настоящее время.

Помните: отметка времени не зависит от часового пояса.

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

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

}

0 голосов
/ 20 июня 2014

Может быть поздний ответ, но вот способ сделать это в одну строку, не используя никаких библиотек:

new SimpleDateFormat("yyyy-MM-dd").parse(new SimpleDateFormat("yyyy-MM-dd").format(YOUR_TIMESTAMP))
0 голосов
/ 16 июня 2016

Для всех ответов, использующих Календарь, вы должны использовать его следующим образом

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