Встановити час на 00:00:00


121

У мене проблема скидання годин на Java. На задану дату я хочу встановити години 00:00:00.

Це мій код:

/**
     * Resets milliseconds, seconds, minutes and hours from the provided date
     *
     * @param date
     * @return
     */
    public static Date trim(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.MILLISECOND, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.HOUR, 0);

        return calendar.getTime();
    }

Проблема полягає в тому, що іноді час є, 12:00:00а іноді він є, 00:00:00і коли я запитую базу даних для сутності, яку було збережено, 07.02.2013 00:00:00і фактичний час сутності, який зберігається, 12:00:00запит не вдається.

Я це знаю 12:00:00 == 00:00:00!

Я використовую AppEngine. Це помилка, що виникає, проблема чи якась інша проблема? Або це залежить від чогось іншого?


Чи може це мати щось спільне з різними локалями чи це відбувається з одного і того ж ПК весь час?
LostBoy

це трапляється, коли я розгортаю аппенгін.
Аделін

Багато інших рішень для відсікання часу: stackoverflow.com/a/1908955/2646526
heenenee

FYI, тривожні старі класи дату, такі як java.util.Date, java.util.Calendarі java.text.SimpleDateFormatтепер застарілі , замінені класами java.time, вбудованими в Java 8 та Java 9. Див. Підручник від Oracle .
Василь Бурк

1
Я використовував calendar.set(Calendar.HOUR_OF_DAY, 0);, за своїм призначенням, це добре працює.
hariprasad

Відповіді:


209

Використовуйте іншу константу замість Calendar.HOUR, використовуйте Calendar.HOUR_OF_DAY.

calendar.set(Calendar.HOUR_OF_DAY, 0);

Calendar.HOURвикористовує 0-11 (для використання з AM / PM) та Calendar.HOUR_OF_DAYвикористовує 0-23.

Щоб цитувати Javadocs:

загальнодоступний статичний фінал in HOUR

Номер поля для отримання та встановлення із зазначенням години ранку чи вдень. HOUR використовується для 12-годинного годинника (0 - 11). Полудень і опівночі представлені 0, а не 12. Напр., О 10: 04: 15.250, ЧАС - 10.

і

загальнодоступний статичний фінал HOUR_OF_DAY

Номер поля для отримання та встановлення із зазначенням години дня. HOUR_OF_DAY використовується для цілодобового годинника. Наприклад, о 10: 04: 15.250 годин HOUR_OF_DAY - 22.

Тестування ("зараз" - близько 13:55, 23 липня 2013 року, тихоокеанський літній час):

public class Main
{
   static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    public static void main(String[] args)
    {
        Calendar now = Calendar.getInstance();
        now.set(Calendar.HOUR, 0);
        now.set(Calendar.MINUTE, 0);
        now.set(Calendar.SECOND, 0);
        System.out.println(sdf.format(now.getTime()));
        now.set(Calendar.HOUR_OF_DAY, 0);
        System.out.println(sdf.format(now.getTime()));
    }
}

Вихід:

$ javac Main.java
$ java Main
2013-07-23 12:00:00
2013-07-23 00:00:00

3
@JarrodRoberson Але використання Calendar.HOURPM не встановило б PM, залишивши його як 12:00.
rgettman

Чи можете ви мені допомогти у створенні LocalDate годин, хвилин та секунди? Я знаю, один із варіантів - дотримуватися DateTime.
Вуді

11
Той, хто створив поля HOUR та HOUR_OF_DAY, мав би бути пошкоджений та поставлений на пайок.
AndroidDev

1
@AndroidDev, хто винайшов am / pm, заслуговує того ж ... Це також стосується
неметрічних

1
FYI, тривожні старі класи дату, такі як java.util.Date, java.util.Calendarі java.text.SimpleDateFormatтепер застарілі , замінені класами java.time, вбудованими в Java 8 та Java 9. Див. Підручник від Oracle .
Василь Бурк

29

java.time

Використання java.timeфреймворку, вбудованого в Java 8 та новіших версій. Дивіться Підручник .

import java.time.LocalTime;
import java.time.LocalDateTime;

LocalDateTime now = LocalDateTime.now(); # 2015-11-19T19:42:19.224
# start of a day
now.with(LocalTime.MIN); # 2015-11-19T00:00
now.with(LocalTime.MIDNIGHT); # 2015-11-19T00:00

Якщо вам не потрібен час дня (години, хвилини, секунди тощо), подумайте про використання LocalDateкласу.

LocalDate.now(); # 2015-11-19

Це має бути нова прийнята відповідь з моменту виходу Java 1.8 з моменту першого запитання.
матова форзація

LocalDateTimeсаме неправильний клас використовувати для цього. Він не може представляти момент, оскільки йому не вистачає жодної концепції часового поясу або зміщення з-за UTC. Телефонувати LocalDateTime.nowмайже ніколи не має сенсу. Використовуйте ZonedDateTimeзамість цього. Інакше ви ігноруєте вирішальні проблеми часового поясу. З одного боку, деякі дати в деяких зонах починаються не о 00:00!
Василь Бурк

12

Ось кілька функцій утиліти, які я використовую для виконання саме цього.

/**
 * sets all the time related fields to ZERO!
 *
 * @param date
 *
 * @return Date with hours, minutes, seconds and ms set to ZERO!
 */
public static Date zeroTime( final Date date )
{
    return DateTimeUtil.setTime( date, 0, 0, 0, 0 );
}

/**
 * Set the time of the given Date
 *
 * @param date
 * @param hourOfDay
 * @param minute
 * @param second
 * @param ms
 *
 * @return new instance of java.util.Date with the time set
 */
public static Date setTime( final Date date, final int hourOfDay, final int minute, final int second, final int ms )
{
    final GregorianCalendar gc = new GregorianCalendar();
    gc.setTime( date );
    gc.set( Calendar.HOUR_OF_DAY, hourOfDay );
    gc.set( Calendar.MINUTE, minute );
    gc.set( Calendar.SECOND, second );
    gc.set( Calendar.MILLISECOND, ms );
    return gc.getTime();
}

6

Ще один спосіб JAVA 8:

LocalDateTime localDateTime = LocalDateTime.now().truncatedTo(ChronoUnit.HOURS);

Але набагато корисніше редагувати дату, яка вже існує.


1
LocalDateTimeне може представляти момент, оскільки в ньому відсутня будь-яка концепція часового поясу або зміщення з-за UTC. Телефонувати LocalDateTime.nowмайже ніколи не має сенсу. Ви повинні використовувати це ZonedDateTimeзамість цього.
Василь Бурк

3

Ви б краще, перш за все, встановити часовий пояс для компонента DateFormat таким чином:

DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));

Тоді ви можете отримати час "00:00:00", пропустивши у форматер 0 мілісекунд:

String time = dateFormat.format(0);

або ви можете створити об’єкт дати:

Date date = new Date(0); // also pass milliseconds
String time = dateFormat.foramt(date);

або ви можете мати більше можливостей за допомогою компонента Calendar, але вам також слід встановити часовий пояс як GMT для екземпляра календаря:

Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"), Locale.US);
calendar.set(Calendar.HOUR_OF_DAY, 5);
calendar.set(Calendar.MINUTE, 37);
calendar.set(Calendar.SECOND, 27);

dateFormat.format(calendar.getTime());

2

тл; д-р

myJavaUtilDate                                 // The terrible `java.util.Date` class is now legacy. Use *java.time* instead.
.toInstant()                                   // Convert this moment in UTC from the legacy class `Date` to the modern class `Instant`.
.atZone( ZoneId.of( "Africa/Tunis" ) )         // Adjust from UTC to the wall-clock time used by the people of a particular region (a time zone).
.toLocalDate()                                 // Extract the date-only portion.
.atStartOfDay( ZoneId.of( "Africa/Tunis" ) )   // Determine the first moment of that date in that zone. The day does *not* always start at 00:00:00.

java.time

Ви використовуєте жахливі старі класи дату, які були витіснені роками тому сучасними класами java.time, визначеними в JSR 310.

DateInstant

Миттєвий java.util.Dateмомент у UTC. Його заміна є Instant. Викликайте нові методи перетворення, додані до старих класів.

Instant instant = myJavaUtilDate.toInstant() ;

Часовий пояс

Вкажіть часовий пояс, у якому ви хочете, щоб ваш новий час дня мав сенс.

Вкажіть правильний час ім'я зони в форматі Continent/Region, наприклад America/Montreal, Africa/Casablancaабо Pacific/Auckland. Ніколи не використовуйте абревіатуру 2-4 літер, наприклад, ESTабо ISTяк вони не є справжніми часовими поясами, не стандартизовані і навіть не унікальні (!).

ZoneId z = ZoneId.of( "America/Montreal" ) ;

ZonedDateTime

Застосуйте ZoneIdдо, Instantщоб отримати ZonedDateTime. Той самий момент, та сама точка на часовій шкалі, але різний час настінного годинника.

ZonedDateTime zdt = instant.atZone( z ) ;

Зміна часу доби

Ви попросили змінити час дня. Застосуйте a, LocalTimeщоб змінити всі частини часу: годину, хвилину, секунду, дробову секунду. Нове ZonedDateTimeє оригінальним, зі значеннями, заснованими на оригіналі. У java.time класи використовують цей незаперечний об'єкти шаблон , щоб забезпечити безпеку потоків .

LocalTime lt = LocalTime.of( 15 , 30 ) ;  // 3:30 PM.
ZonedDateTime zdtAtThreeThirty = zdt.with( lt ) ; 

Перша хвилина дня

Але ви запитували конкретно 00:00. Отже, мабуть, вам хочеться першої миті дня. Остерігайтеся: деякі дні в деяких зонах не починаються о 00:00:00. Вони можуть розпочатися в інший час, наприклад, 01:00:00 через такі аномалії, як літній час (DST).

Нехай java.time визначає перший момент. Витягніть частину лише для дати. Потім пройдіть часовий пояс, щоб отримати перший момент.

LocalDate ld = zdt.toLocalDate() ;
ZonedDateTime zdtFirstMomentOfDay = ld.atStartOfDay( z ) ;

Налаштувати на UTC

Якщо вам потрібно повернутися до UTC, витягніть Instant.

Instant instant = zdtFirstMomentOfDay.toInstant() ;

InstantDate

Якщо вам потрібна java.util.Dateвзаємодія зі старим кодом, ще не оновленим до java.time , конвертуйте.

java.util.Date d = java.util.Date.from( instant ) ;

1

Зробити це може бути простіше (на Java 8)

LocalTime.ofNanoOfDay(0)

Дякую, я працював з іншими речами останні 2 роки, і Java 6/7 до цього. Зараз я повернувся до Java (після роботи з кількома речами над Groovy) і мені подобаються відмінності Java 8.
месія

1

Ми можемо встановити частину часу java.util.Date до 00:00:00 За допомогою класу LocalDate Java 8 / Joda-datetime api :

Date datewithTime = new Date() ; // ex: Sat Apr 21 01:30:44 IST 2018
LocalDate localDate = LocalDate.fromDateFields(datewithTime);
Date datewithoutTime = localDate.toDate(); // Sat Apr 21 00:00:00 IST 2018

1

Якщо вам потрібен формат 00:00:00 в рядку, ви повинні використовувати SimpleDateFormat, як показано нижче. Використання "H" замість "h".

Date today = new Date();
SimpleDateFormat ft = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss"); 
//not SimpleDateFormat("dd-MM-yyyy hh:mm:ss")
Calendar calendarDM = Calendar.getInstance();
calendarDM.setTime(today);
calendarDM.set(Calendar.HOUR, 0);
calendarDM.set(Calendar.MINUTE, 0);
calendarDM.set(Calendar.SECOND, 0);
System.out.println("Current Date: " + ft.format(calendarDM.getTime()));

//Result is: Current Date: 29-10-2018 00:00:00

0

Ще один спосіб зробити це - використовувати DateFormat без жодних секунд:

public static Date trim(Date date) {
    DateFormat format = new SimpleDateFormat("dd.MM.yyyy");
    Date trimmed = null;
    try {
        trimmed = format.parse(format.format(date));
    } catch (ParseException e) {} // will never happen
    return trimmed;
}

0

Ви можете зробити це за допомогою наступного:

Calendar cal = Calendar.getInstance();
cal.set(year, month, dayOfMonth, 0, 0, 0);
Date date = cal.getTime();

0

Оскільки Java8 додає нові функції дати, ми можемо це зробити легко.


    // If you have instant, then:
    Instant instant1 = Instant.now();
    Instant day1 = instant1.truncatedTo(ChronoUnit.DAYS);
    System.out.println(day1); //2019-01-14T00:00:00Z

    // If you have Date, then:
    Date date = new Date();
    Instant instant2 = date.toInstant();
    Instant day2 = instant2.truncatedTo(ChronoUnit.DAYS);
    System.out.println(day2); //2019-01-14T00:00:00Z

    // If you have LocalDateTime, then:
    LocalDateTime dateTime = LocalDateTime.now();
    LocalDateTime day3 = dateTime.truncatedTo(ChronoUnit.DAYS);
    System.out.println(day3); //2019-01-14T00:00
    String format = day3.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
    System.out.println(format);//2019-01-14T00:00:00


LocalDateTimeне може представляти момент, оскільки в ньому відсутня будь-яка концепція часового поясу або зміщення з-за UTC. Телефонувати LocalDateTime.nowмайже ніколи не має сенсу. Ви повинні використовувати це ZonedDateTimeзамість цього.
Василь Бурк
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.