Wie erhalte ich die Start- und Endzeit eines Tages?
Code wie dieser ist nicht korrekt:
private Date getStartOfDay(Date date) {
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DATE);
calendar.set(year, month, day, 0, 0, 0);
return calendar.getTime();
}
private Date getEndOfDay(Date date) {
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
int day = calendar.get(Calendar.DATE);
calendar.set(year, month, day, 23, 59, 59);
return calendar.getTime();
}
Es ist nicht millisekundengenau.
Antworten:
tl; dr
Tagesanfang
Holen Sie sich die volle Länge des heutigen Tages aus einer Zeitzone.
Verwendung des Half-Open-Ansatzes, bei dem der Anfang inklusive und das Ende exklusiv ist . Dieser Ansatz behebt den Fehler in Ihrem Code, der die letzte Sekunde des Tages nicht berücksichtigt.
Sehen Sie die gleichen Momente in UTC.
Wenn Sie den gesamten Tag eines Datums wie in UTC und nicht in einer Zeitzone anzeigen möchten, verwenden Sie
OffsetDateTime
.Diese
OffsetDateTime
Objekte befinden sich bereits in UTC. Sie können sie jedoch aufrufen,toInstant
wenn Sie solche Objekte benötigen, die sich per Definition immer in UTC befinden.Tipp: Möglicherweise möchten Sie Ihrem Projekt die ThreeTen-Extra- Bibliothek hinzufügen , um deren
Interval
Klasse zur Darstellung dieses Objektpaars zu verwendenInstant
. Diese Klasse bietet nützliche Methoden zum Vergleich wieabuts
,overlaps
,contains
und vieles mehr.Halb offen
Die Antwort von mprivat ist richtig. Sein Ziel ist es, nicht zu versuchen, das Ende eines Tages zu erreichen, sondern mit "vor Beginn des nächsten Tages" zu vergleichen. Seine Idee ist als "Half-Open" -Ansatz bekannt, bei dem eine Zeitspanne einen Anfang hat, der inklusiv ist, während das Ende exklusiv ist .
Joda-Time 2.3 bietet genau zu diesem Zweck eine Methode, um den ersten Moment des Tages zu erhalten :
withTimeAtStartOfDay()
. Ähnlich in java.time ,LocalDate::atStartOfDay
.Durchsuchen Sie StackOverflow nach "joda half-open" , um weitere Diskussionen und Beispiele zu sehen.
Siehe diesen Beitrag, Zeitintervalle und andere Bereiche sollten von Bill Schneider halb offen sein .
Vermeiden Sie ältere Datums- und Zeitklassen
Die Klassen java.util.Date und .Calendar sind notorisch problematisch. Vermeide sie.
Verwenden Sie java.time- Klassen. Das java.time- Framework ist der offizielle Nachfolger der äußerst erfolgreichen Joda-Time- Bibliothek.
java.time
Das java.time-Framework ist in Java 8 und höher integriert. Back-portiert Java 6 und 7 in dem ThreeTen-Backport - Projekt weiter zu Android angepasst im ThreeTenABP Projekt.
An
Instant
ist ein Moment auf der Zeitachse in UTC mit einer Auflösung von Nanosekunden .Wenden Sie eine Zeitzone an, um die Wanduhrzeit für einen bestimmten Ort zu ermitteln.
Um den ersten Moment des Tages zu erleben, gehen Sie die
LocalDate
Klasse und ihreatStartOfDay
Methode durch.Holen Sie sich mit dem Half-Open-Ansatz den ersten Moment des folgenden Tages.
Derzeit fehlt dem java.time-Framework eine
Interval
Klasse, wie unten für Joda-Time beschrieben. Das ThreeTen-Extra- Projekt erweitert java.time jedoch um zusätzliche Klassen. Dieses Projekt ist das Testfeld für mögliche zukünftige Ergänzungen von java.time. Zu seinen Klassen gehörtInterval
. Konstruieren Sie eine,Interval
indem Sie ein Objektpaar übergebenInstant
. Wir können eineInstant
aus unserenZonedDateTime
Objekten extrahieren .Über java.time
Das java.time- Framework ist in Java 8 und höher integriert. Diese Klassen verdrängen die lästigen alten Legacy - Datum-Zeit - Klassen wie
java.util.Date
,Calendar
, &SimpleDateFormat
.Weitere Informationen finden Sie im Oracle-Lernprogramm . Suchen Sie im Stapelüberlauf nach vielen Beispielen und Erklärungen. Die Spezifikation ist JSR 310 .
Das Joda-Time- Projekt, das sich jetzt im Wartungsmodus befindet , empfiehlt die Migration zu den Klassen java.time .
Sie können java.time- Objekte direkt mit Ihrer Datenbank austauschen . Verwenden Sie einen JDBC-Treiber, der mit JDBC 4.2 oder höher kompatibel ist . Keine Notwendigkeit für Zeichenfolgen, keine Notwendigkeit für
java.sql.*
Klassen. Hibernate 5 und JPA 2.2 unterstützen java.time .Woher bekomme ich die java.time-Klassen?
Joda-Zeit
UPDATE: Das Joda-Time-Projekt befindet sich jetzt im Wartungsmodus und empfiehlt die Migration zu den Klassen java.time . Ich lasse diesen Abschnitt für die Geschichte intakt.
Joda-Time hat drei Klassen eine Zeitspanne auf verschiedene Weise darstellen:
Interval
,Period
, undDuration
. AnInterval
hat einen bestimmten Anfang und ein bestimmtes Ende auf der Zeitachse des Universums. Dies passt zu unserem Bedürfnis, "einen Tag" darzustellen.Wir rufen die Methode auf,
withTimeAtStartOfDay
anstatt die Tageszeit auf Null zu setzen. Aufgrund der Sommerzeit und anderer Anomalien ist der erste Moment des Tages möglicherweise nicht der richtige00:00:00
.Beispielcode mit Joda-Time 2.3.
Wenn Sie müssen, können Sie in ein java.util.Date konvertieren.
quelle
LocalDateTime
Java 8
Aktualisieren : Ich habe hinzugefügt , um diese zwei Methoden , um meine Java Utility - Klassen hier
Es befindet sich im Maven Central Repository unter:
Java 7 und früher
Mit Apache Commons
Ohne Apache Commons
quelle
getStartOfDay
sollte sein:LocalDateTime startOfDay = localDateTime.with(LocalTime.MIN);
Dh LocalTime, nicht LocalDateTime.getEndOfDay(Date date)
.getStartOfDay(Date date)
Die Methoden im Abschnitt Java 8 sind korrekt. Mit LocalDateTime.MAX und .MIN können Sie die frühestmöglichen Daten in der Vergangenheit und in der Zukunft festlegen, nicht den Anfang und das Ende eines Tages. Stattdessen würde ich .atStartOfDay () für start und .plusDays (1) .atStartOfDay (). MinusNanos (1) für end vorschlagen.localDateTimeToDate(LocalDateTime startOfDay)
In getEndOfDay können Sie Folgendes hinzufügen:
Obwohl mathematisch gesehen, können Sie das Ende eines Tages nur angeben, indem Sie sagen, dass es "vor dem Beginn des nächsten Tages" ist.
Anstatt zu sagen,
if(date >= getStartOfDay(today) && date <= getEndOfDay(today))
sollten Sie sagen :if(date >= getStartOfDay(today) && date < getStartOfDay(tomorrow))
. Das ist eine viel solidere Definition (und Sie müssen sich keine Gedanken über die Millisekundengenauigkeit machen).quelle
java.time
Verwenden eines
java.time
in Java 8 integrierten Frameworks.quelle
Local…
Klassen haben kein Konzept für Zeitzonen und passen sich an Anomalien an. In einigen Zeitzonen wird beispielsweise die Sommerzeit um Mitternacht umgeschaltet, sodass der erste Moment des Tages auf der Uhrzeit01:00:00.0
(1 Uhr morgens) liegt und nicht auf dem00:00:00.0
von diesem Code erzeugten Wert. Verwenden SieZonedDateTime
stattdessen.Eine zusätzliche Möglichkeit, den Tagesanfang mit java8 java.time.ZonedDateTime zu ermitteln,
LocalDateTime
besteht darin, die Eingabe ZonedDateTime auf DAYS zu kürzen:quelle
Für Java 8 funktionieren die folgenden einzeiligen Anweisungen. In diesem Beispiel verwende ich die UTC-Zeitzone. Bitte überlegen Sie, die aktuell verwendete Zeitzone zu ändern.
Wenn kein Zeitunterschied zur Ausgabe besteht. Versuchen:
ZoneOffset.ofHours(0)
quelle
toInstant
ist unzulässig und konzeptionell redundant.Java 8 oder ThreeTenABP
ZonedDateTime
LocalDateTime
Ich hoffe das hilft jemandem.
quelle
Ich habe diesen Code ausprobiert und er funktioniert gut!
quelle
ZonedDateTime
undInstant
zu Ihrer Verfügung haben, besteht keine Notwendigkeit, jemals zu verwendenjava.sql.Timestamp
. Diese Klasse ist eine der schrecklichen alten Legacy-Klassen, die jetzt durch die java.time- Klassen ersetzt werden. Ab JDBC 4.2 können wir java.time- Objekte direkt mit der Datenbank austauschen . Ihre Vermischung von Vermächtnis und modernem Unterricht macht für mich keinen Sinn.Eine andere Lösung, die von keinem Framework abhängt, ist:
Beachten Sie, dass die UTC-basierte Zeit zurückgegeben wird
quelle
calendar.setTimeInMillis (0); gibt Ihnen Genauigkeit bis zu Millisekunden
quelle
Ich weiß, dass es etwas spät ist, aber im Fall von Java 8 können Sie den folgenden Code verwenden, wenn Sie OffsetDateTime verwenden (das viele Vorteile wie TimeZone, Nanosekunden usw. bietet):
quelle
Ich hatte einige Unannehmlichkeiten mit allen Lösungen, weil ich den Typ der Sofortvariablen brauchte und die Zeitzone immer störte, alles zu ändern und dann Lösungen zu kombinieren. Ich sah, dass dies eine gute Option ist.
und wir haben als Ergebnis
Ich hoffe es hilft dir
quelle
Instant
Objekte. Tipp: Möglicherweise möchten Sie die ThreeTen-Extra- Bibliothek zu Ihrem Projekt hinzufügen , um dessenInterval
Klasse zu verwenden.Ich denke, das Einfachste wäre so etwas wie:
Diese Millis können dann gemäß Ihren Anforderungen mit Joda Time in Kalender, Instant oder LocalDate konvertiert werden.
quelle
quelle