Ustaw czas na 00:00:00

121

Mam problem ze zresetowaniem godzin w Javie. Na dany dzień chcę ustawić godziny na 00:00:00.

To jest mój kod:

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

Problem polega na tym, że czasami jest czas, 12:00:00a czasami tak jest, 00:00:00a kiedy wykonuję zapytanie w bazie danych o jednostkę, która została zapisana, 07.02.2013 00:00:00a rzeczywisty czas jednostki, który jest przechowywany, 12:00:00kończy się niepowodzeniem.

Wiem to 12:00:00 == 00:00:00!

Używam AppEngine. Czy to błąd, problem z aplikacją lub inny problem? A może zależy to od czegoś innego?

Adelin
źródło
Czy może to mieć coś wspólnego z różnymi lokalizacjami, czy też dzieje się to cały czas z tego samego komputera?
LostBoy
dzieje się tak, gdy wdrażam w appengine.
Adelin,
Wiele innych rozwiązań na skracanie czasu: stackoverflow.com/a/1908955/2646526
heenenee
FYI, kłopotliwe stare klasy daty i godziny, takie jak java.util.Date, java.util.Calendari java.text.SimpleDateFormatsą teraz starsze , zastąpione przez klasy java.time wbudowane w Java 8 i Java 9. Zobacz samouczek Oracle .
Basil Bourque
1
Użyłem calendar.set(Calendar.HOUR_OF_DAY, 0);, w moim celu, działa dobrze.
hariprasad

Odpowiedzi:

209

Użyj innej stałej zamiast Calendar.HOUR, użyj Calendar.HOUR_OF_DAY.

calendar.set(Calendar.HOUR_OF_DAY, 0);

Calendar.HOURużywa 0-11 (do użytku z AM / PM) i Calendar.HOUR_OF_DAYużywa 0-23.

Cytując Javadocs:

public static final int HOUR

Numer pola do pobierania i ustawiania wskazujący godzinę rano lub po południu. GODZINA jest używana jako zegar 12-godzinny (0 - 11). Południe i północ są reprezentowane przez 0, a nie przez 12. Np. O 10:04:15.250 GODZINA wynosi 10.

i

publiczny statyczny koniec dnia HOUR_OF_DAY

Numer pola do pobrania i zbioru wskazujący godzinę dnia. HOUR_OF_DAY jest używany jako zegar 24-godzinny. Np. O 10:04: 15.250 godzina HOUR_OF_DAY to 22.

Testowanie („teraz” to obecnie około 14:55, 23 lipca 2013 r. Czasu pacyficznego letniego):

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

Wynik:

$ javac Main.java
$ java Main
2013-07-23 12:00:00
2013-07-23 00:00:00
rgettman
źródło
3
@JarrodRoberson Ale użycie Calendar.HOURnie ustawiłoby PM na AM, pozostawiając to na 12:00.
rgettman
Czy możesz mi pomóc w tworzeniu LocalDate z godzinami, minutami i sekundami? Wiem, że jedną z opcji jest śledzenie daty i godziny.
Woody
11
Ktokolwiek stworzył pole HOUR i HOUR_OF_DAY, powinien zostać wychłostany i zaopatrzony w racje.
AndroidDev
1
@AndroidDev, który wynalazł am / pm, zasługuje na to samo ... Dotyczy to również standardów niemetrycznych
Dediqated
1
FYI, kłopotliwe stare klasy daty i godziny, takie jak java.util.Date, java.util.Calendari java.text.SimpleDateFormatsą teraz starsze , zastąpione przez klasy java.time wbudowane w Java 8 i Java 9. Zobacz samouczek Oracle .
Basil Bourque
29

java.time

Korzystanie z java.timeframeworka wbudowanego w Javę 8 i nowszych. Zobacz samouczek .

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

Jeśli nie potrzebujesz części dotyczącej pory dnia (godziny, minuty, sekundy itp.), Rozważ użycie LocalDateklasy.

LocalDate.now(); # 2015-11-19
Przemek
źródło
To powinna być nowa zaakceptowana odpowiedź, ponieważ Java 1.8 została wydana od czasu pierwszego zadania tego pytania.
Matt forsythe
LocalDateTimejest dokładnie niewłaściwą klasą do tego celu. Nie może przedstawiać momentu, ponieważ nie ma pojęcia strefy czasowej ani przesunięcia względem UTC. Dzwonienie LocalDateTime.nowprawie nigdy nie ma sensu. Użyj ZonedDateTimezamiast tego. W przeciwnym razie ignorujesz kluczowe problemy ze strefą czasową. Po pierwsze, niektóre daty w niektórych strefach nie zaczynają się o 00:00!
Basil Bourque
12

Oto kilka funkcji narzędziowych, których używam do tego.

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

źródło
6

Jeszcze jeden sposób na JAVA 8:

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

Ale o wiele bardziej przydatne jest edytowanie daty, która już istnieje.

thorinkor
źródło
1
LocalDateTimenie może przedstawiać chwili, ponieważ brakuje w niej koncepcji strefy czasowej lub przesunięcia względem UTC. Dzwonienie LocalDateTime.nowprawie nigdy nie ma sensu. Zamiast tego powinieneś używać ZonedDateTime.
Basil Bourque
3

Lepiej byłoby ustawić strefę czasową przede wszystkim na składnik DateFormat w następujący sposób:

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

Następnie możesz uzyskać czas „00:00:00”, przekazując 0 milisekund do programu formatującego:

String time = dateFormat.format(0);

lub możesz stworzyć obiekt Date:

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

lub możesz mieć więcej możliwości przy użyciu komponentu Kalendarz, ale powinieneś również ustawić strefę czasową jako GMT dla wystąpienia kalendarza:

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());
Dmitriy Smerchinskiy
źródło
2

tl; dr

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

Używasz okropnych starych klas daty i czasu, które lata temu zostały wyparte przez nowoczesne klasy java.time zdefiniowane w JSR 310.

DateInstant

A java.util.Datereprezentują chwilę w UTC. Jego zamiennikiem jest Instant. Wywołaj nowe metody konwersji dodane do starych klas.

Instant instant = myJavaUtilDate.toInstant() ;

Strefa czasowa

Określ strefę czasową, w której ma mieć sens nowa pora dnia.

Określ prawidłową nazwę strefy czasowej w formacie Continent/Region, takie jak America/Montreal, Africa/Casablancalub Pacific/Auckland. Nigdy nie używaj skrótów składających się z 2-4 liter, takich jak ESTlub, ISTponieważ nie są to prawdziwe strefy czasowe, nie są standaryzowane, a nawet nie są unikalne (!).

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

ZonedDateTime

Zastosuj ZoneIddo, Instantaby uzyskać ZonedDateTime. Ten sam moment, ten sam punkt na osi czasu, ale inny zegar ścienny.

ZonedDateTime zdt = instant.atZone( z ) ;

Zmiana pory dnia

Poprosiłeś o zmianę pory dnia. Zastosuj a, LocalTimeaby zmienić wszystkie części dotyczące pory dnia: godzina, minuta, sekunda, ułamek sekundy. ZonedDateTimeTworzony jest nowy egzemplarz z wartościami opartymi na oryginale. W java.time klas użyć tej niezmiennej obiektów wzór, aby zapewnić wątku bezpieczeństwa .

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

Pierwsza chwila dnia

Ale prosiłeś specjalnie o 00:00. Więc najwyraźniej chcesz pierwszej chwili dnia. Uwaga: niektóre dni w niektórych strefach nie zaczynają się o 00:00:00. Mogą rozpocząć się w innym czasie, na przykład 01:00:00 z powodu anomalii, takich jak czas letni (DST).

Niech java.time określi pierwszy moment. Wyodrębnij część zawierającą tylko datę. Następnie przejdź przez strefę czasową, aby uzyskać pierwszą chwilę.

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

Dostosuj do UTC

Jeśli chcesz wrócić do UTC, wyodrębnij plik Instant.

Instant instant = zdtFirstMomentOfDay.toInstant() ;

InstantDate

Jeśli potrzebujesz java.util.Datewspółdziałać ze starym kodem, który nie został jeszcze zaktualizowany do java.time , przekonwertuj.

java.util.Date d = java.util.Date.from( instant ) ;
Basil Bourque
źródło
1

Może to być łatwiejsze (w Javie 8)

LocalTime.ofNanoOfDay(0)
meszias
źródło
Dziękuję, pracowałem z innymi rzeczami przez ostatnie 2 lata, a wcześniej z Javą 6/7. Wróciłem teraz do Javy (po kilku pracach nad Groovy) i polubiłem różnice w Javie 8.
meszias
1

Możemy ustawić część czasu java.util.Date na 00:00:00 Używając klasy LocalDate api Java 8 / Joda-datetime :

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
Atishay
źródło
1

Jeśli potrzebujesz formatu 00:00:00 w ciągu, powinieneś użyć SimpleDateFormat, jak poniżej. Używanie „H” zamiast „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
Ngô Ngọc Quang
źródło
0

Innym sposobem na zrobienie tego byłoby użycie DateFormat bez żadnych sekund:

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;
}
MMascarin
źródło
0

Możesz to zrobić w następujący sposób:

Calendar cal = Calendar.getInstance();
cal.set(year, month, dayOfMonth, 0, 0, 0);
Date date = cal.getTime();
Sagar Patel
źródło
0

Ponieważ Java8 dodaje nowe funkcje Date, możemy to łatwo zrobić.


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

Chao Jiang
źródło
LocalDateTimenie może przedstawiać chwili, ponieważ brakuje w niej koncepcji strefy czasowej lub przesunięcia względem UTC. Dzwonienie LocalDateTime.nowprawie nigdy nie ma sensu. Zamiast tego powinieneś używać ZonedDateTime.
Basil Bourque