Stellen Sie die Zeit auf 00:00:00 ein

121

Ich habe ein Problem beim Zurücksetzen der Stunden in Java. Für ein bestimmtes Datum möchte ich die Stunden auf 00:00:00 einstellen.

Das ist mein Code:

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

Das Problem ist, dass manchmal die Zeit ist 12:00:00und manchmal ist 00:00:00und wenn ich die Datenbank nach einer Entität abfrage, auf 07.02.2013 00:00:00der gespeichert wurde, und die tatsächliche Entitätszeit, die gespeichert wird, 12:00:00die Abfrage fehlschlägt.

Ich weiß das 12:00:00 == 00:00:00!

Ich benutze AppEngine. Ist dies ein Appengine-Fehler, ein Problem oder ein anderes Problem? Oder hängt es von etwas anderem ab?

Adelin
quelle
Könnte dies etwas mit verschiedenen Gebietsschemas zu tun haben oder geschieht dies immer auf demselben PC?
LostBoy
Es passiert, wenn ich auf Appengine bereitstelle.
Adelin
Viele andere Lösungen zur Verkürzung der
heenenee
Zu Ihrer Information, die störenden alten Datum Zeitklassen wie java.util.Date, java.util.Calendarund java.text.SimpleDateFormatsind jetzt Erbe , durch die verdrängte java.time Klassen in Java gebaut 8 & Java 9. Siehe Tutorial von Oracle .
Basil Bourque
1
Ich habe calendar.set(Calendar.HOUR_OF_DAY, 0);für meinen Zweck verwendet, es funktioniert gut.
Hariprasad

Antworten:

209

Verwenden Sie eine andere Konstante statt Calendar.HOUR, Verwendung Calendar.HOUR_OF_DAY.

calendar.set(Calendar.HOUR_OF_DAY, 0);

Calendar.HOURverwendet 0-11 (zur Verwendung mit AM / PM) und Calendar.HOUR_OF_DAYverwendet 0-23.

Um die Javadocs zu zitieren:

public static final int STUNDE

Feldnummer für get und set, die die Stunde des Morgens oder Nachmittags angibt. HOUR wird für die 12-Stunden-Uhr (0 - 11) verwendet. Mittag und Mitternacht werden durch 0 und nicht durch 12 dargestellt. ZB um 10: 04: 15.250 Uhr ist die STUNDE 10.

und

public static final int HOUR_OF_DAY

Feldnummer für get und set, die die Stunde des Tages angibt. HOUR_OF_DAY wird für die 24-Stunden-Uhr verwendet. ZB um 10: 04: 15.250 Uhr ist der HOUR_OF_DAY 22.

Testen ("jetzt" ist derzeit ca. 14:55 Uhr am 23. Juli 2013 Pacific Daylight Time):

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

Ausgabe:

$ javac Main.java
$ java Main
2013-07-23 12:00:00
2013-07-23 00:00:00
rgettman
quelle
3
@JarrodRoberson Aber mit Calendar.HOURwürde PM nicht auf AM gesetzt, so dass es 12:00 Uhr ist.
Rgettman
Können Sie mir bitte beim Erstellen eines LocalDate mit Stunden, Minuten und Sekunden helfen? Ich weiß, dass eine Option darin besteht, DateTime zu folgen.
Woody
11
Wer auch immer das Feld HOUR und HOUR_OF_DAY erstellt hat, sollte ausgepeitscht und rationiert werden.
AndroidDev
1
@ AndroidDev, wer am / pm erfunden hat, verdient dasselbe ... Dies gilt auch für nicht metrische Standards
Dediqated
1
Zu Ihrer Information, die störenden alten Datum Zeitklassen wie java.util.Date, java.util.Calendarund java.text.SimpleDateFormatsind jetzt Erbe , durch die verdrängte java.time Klassen in Java gebaut 8 & Java 9. Siehe Tutorial von Oracle .
Basil Bourque
29

java.time

Verwenden des java.timein Java 8 und höher integrierten Frameworks. Siehe Tutorial .

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

Wenn Sie keine Tageszeit benötigen (Stunden-, Minuten-, Sekunden- usw. Teile), sollten Sie den LocalDateUnterricht in Betracht ziehen .

LocalDate.now(); # 2015-11-19
Przemek
quelle
Dies sollte die neu akzeptierte Antwort sein, da Java 1.8 seit dem ersten Stellen dieser Frage veröffentlicht wurde.
Matt Forsythe
LocalDateTimeist genau die falsche Klasse dafür. Es kann keinen Moment darstellen, da es kein Konzept für Zeitzone oder Versatz von UTC gibt. Anrufen LocalDateTime.nowmacht fast nie Sinn. Verwenden Sie ZonedDateTimestattdessen. Andernfalls ignorieren Sie wichtige Zeitzonenprobleme. Zum einen beginnen einige Daten in einigen Zonen nicht um 00:00 Uhr!
Basil Bourque
12

Hier sind einige Dienstprogrammfunktionen, die ich verwende, um genau dies zu tun.

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

quelle
6

Noch ein JAVA 8 Weg:

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

Es ist jedoch viel nützlicher, das bereits vorhandene Datum zu bearbeiten.

Thorinkor
quelle
1
LocalDateTimekann keinen Moment darstellen, da es kein Konzept für Zeitzone oder Versatz von UTC gibt. Anrufen LocalDateTime.nowmacht fast nie Sinn. Sie sollten ZonedDateTimestattdessen verwenden.
Basil Bourque
3

Sie sollten die Zeitzone in erster Linie wie folgt auf die DateFormat-Komponente festlegen:

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

Dann können Sie die Zeit "00:00:00" erhalten, indem Sie 0 Millisekunden an den Formatierer übergeben:

String time = dateFormat.format(0);

oder Sie können ein Datumsobjekt erstellen:

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

oder Sie können mit der Kalenderkomponente mehr Möglichkeiten haben, aber Sie sollten auch die Zeitzone als GMT für die Kalenderinstanz festlegen:

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

Sie verwenden schreckliche alte Datums- / Uhrzeitklassen , die vor Jahren durch die in JSR 310 definierten modernen java.time- Klassen ersetzt wurden.

DateInstant

A java.util.Daterepräsentiert einen Moment in UTC. Sein Ersatz ist Instant. Rufen Sie die neuen Konvertierungsmethoden auf, die den alten Klassen hinzugefügt wurden.

Instant instant = myJavaUtilDate.toInstant() ;

Zeitzone

Geben Sie die Zeitzone an, in der Ihre neue Tageszeit sinnvoll sein soll.

Geben Sie einen richtigen Zeitzonennamen im Format Continent/Region, wie zum Beispiel America/Montreal, Africa/Casablancaoder Pacific/Auckland. Verwenden Sie niemals die Abkürzung für 2-4 Buchstaben, wie z. B. ESToder, ISTda es sich nicht um echte Zeitzonen handelt, die nicht standardisiert und nicht einmal eindeutig (!) Sind.

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

ZonedDateTime

Wenden Sie das ZoneIdan Instant, um eine zu erhalten ZonedDateTime. Gleicher Moment, gleicher Punkt auf der Zeitachse, aber andere Wanduhrzeit.

ZonedDateTime zdt = instant.atZone( z ) ;

Tageszeit ändern

Sie haben darum gebeten, die Tageszeit zu ändern. Wenden Sie a LocalTimean, um alle Tageszeitteile zu ändern: Stunde, Minute, Sekunde, Bruchteil einer Sekunde. Ein neues ZonedDateTimewird instanziiert, wobei die Werte auf dem Original basieren. Die java.time- Klassen verwenden dieses unveränderliche Objektmuster , um Thread-Sicherheit zu gewährleisten .

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

Erster Moment des Tages

Aber Sie haben speziell nach 00:00 gefragt. Anscheinend wollen Sie also den ersten Moment des Tages. Achtung: Einige Tage in einigen Zonen beginnen nicht um 00:00:00 Uhr. Sie können aufgrund von Anomalien wie der Sommerzeit (DST) zu einem anderen Zeitpunkt wie z. B. 01:00:00 Uhr beginnen.

Lassen Sie java.time den ersten Moment bestimmen. Extrahieren Sie den Nur-Datum-Teil. Übergeben Sie dann die Zeitzone, um den ersten Moment zu erhalten.

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

Auf UTC einstellen

Wenn Sie zu UTC zurückkehren müssen, extrahieren Sie eine Instant.

Instant instant = zdtFirstMomentOfDay.toInstant() ;

InstantDate

Wenn Sie einen benötigen java.util.Date, um mit altem Code zusammenzuarbeiten, der noch nicht auf java.time aktualisiert wurde , konvertieren Sie.

java.util.Date d = java.util.Date.from( instant ) ;
Basil Bourque
quelle
1

Dies könnte einfacher sein (In Java 8)

LocalTime.ofNanoOfDay(0)
Meszias
quelle
Vielen Dank, ich habe in den letzten 2 Jahren mit anderen Dingen gearbeitet und zuvor mit Java 6/7. Ich bin jetzt wieder bei Java (nachdem ich mit ein paar Dingen an Groovy gearbeitet habe) und mag Java 8-Unterschiede.
Meszias
1

Wir können den Zeitteil java.util.Date auf 00:00:00 setzen. Mithilfe der LocalDate-Klasse von 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
Atishay
quelle
1

Wenn Sie das Format 00:00:00 in einer Zeichenfolge benötigen, sollten Sie SimpleDateFormat wie folgt verwenden. Verwenden Sie "H" anstelle von "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
quelle
0

Eine andere Möglichkeit, dies zu tun, wäre die Verwendung eines DateFormats ohne Sekunden:

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

Sie können dies entweder folgendermaßen tun:

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

Wenn Java8 neue Datumsfunktionen hinzufügt, können wir dies problemlos tun.


    // 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
quelle
LocalDateTimekann keinen Moment darstellen, da es kein Konzept für Zeitzone oder Versatz von UTC gibt. Anrufen LocalDateTime.nowmacht fast nie Sinn. Sie sollten ZonedDateTimestattdessen verwenden.
Basil Bourque