Установите время на 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. Это ошибка appengine, проблема или какая-то другая проблема? Или это от чего-то еще зависит?


Может ли это иметь какое-то отношение к разным регионам или все время происходит с одного и того же ПК?
LostBoy

это происходит, когда я развертываю приложение на appengine.
Adelin

Множество других решений для сокращения времени: stackoverflow.com/a/1908955/2646526
heenenee 02

К вашему сведению, неприятные старые классы даты и времени, такие как java.util.Date, java.util.Calendarи java.text.SimpleDateFormat, теперь унаследованы , их вытеснили классы java.time, встроенные в Java 8 и Java 9. См. Учебник от Oracle .
Basil Bourque

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:

public static final int ЧАС

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

и

public static final int HOUR_OF_DAY

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

Тестирование («сейчас» сейчас около 14: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 не устанавливается значение AM, а остается 12:00.
rgettman

Не могли бы вы помочь мне создать LocalDate с часами, минутами и секундами? Я знаю, что один из вариантов - следовать DateTime.
Woody

11
Тот, кто создал поле HOUR и HOUR_OF_DAY, должен был быть порчен и поставлен на пайки.
AndroidDev

1
@AndroidDev, кто изобрел am / pm, заслуживает того же ... Это также касается неметрических стандартов
Dediqated

1
К вашему сведению, неприятные старые классы даты и времени, такие как java.util.Date, java.util.Calendarи java.text.SimpleDateFormat, теперь унаследованы , их вытеснили классы java.time, встроенные в Java 8 и Java 9. См. Учебник от Oracle .
Basil Bourque

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!
Basil

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Вместо этого вы должны использовать .
Basil

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 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

A 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.
meszias

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 добавляет новые функции Date, мы можем легко это сделать.


    // 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Вместо этого вы должны использовать .
Basil
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.