tl; dr
LocalDate // Represents an entire day, without time-of-day and without time zone.
.now( // Capture the current date.
ZoneId.of( "Asia/Tokyo" ) // Returns a `ZoneId` object.
) // Returns a `LocalDate` object.
.atStartOfDay( // Determines the first moment of the day as seen on that date in that time zone. Not all days start at 00:00!
ZoneId.of( "Asia/Tokyo" )
) // Returns a `ZonedDateTime` object.
Inizio della giornata
Ottieni l'intera durata della giornata odierna come si vede in un fuso orario.
Utilizzando l'approccio Half-Open, dove è l'inizio inclusivo mentre il finale è esclusivo . Questo approccio risolve il difetto nel codice che non riesce a tenere conto dell'ultimo secondo della giornata.
ZoneId zoneId = ZoneId.of( "Africa/Tunis" ) ;
LocalDate today = LocalDate.now( zoneId ) ;
ZonedDateTime zdtStart = today.atStartOfDay( zoneId ) ;
ZonedDateTime zdtStop = today.plusDays( 1 ).atStartOfDay( zoneId ) ;
zdtStart.toString () = 2020-01-30T00: 00 + 01: 00 [Africa / Tunisi]
zdtStop.toString () = 2020-01-31T00: 00 + 01: 00 [Africa / Tunisi]
Guarda gli stessi momenti in UTC.
Instant start = zdtStart.toInstant() ;
Instant stop = zdtStop.toInstant() ;
start.toString () = 2020-01-29T23: 00: 00Z
stop.toString () = 2020-01-30T23: 00: 00Z
Se desideri visualizzare l'intero giorno di una data in UTC anziché in un fuso orario, utilizza OffsetDateTime
.
LocalDate today = LocalDate.now( ZoneOffset.UTC ) ;
OffsetDateTime odtStart = today.atTime( OffsetTime.MIN ) ;
OffsetDateTime odtStop = today.plusDays( 1 ).atTime( OffsetTime.MIN ) ;
odtStart.toString () = 2020-01-30T00: 00 + 18: 00
odtStop.toString () = 2020-01-31T00: 00 + 18: 00
Questi OffsetDateTime
oggetti saranno già in UTC, ma puoi chiamare toInstant
se hai bisogno di tali oggetti che sono sempre in UTC per definizione.
Instant start = odtStart.toInstant() ;
Instant stop = odtStop.toInstant() ;
start.toString () = 2020-01-29T06: 00: 00Z
stop.toString () = 2020-01-30T06: 00: 00Z
Suggerimento: potresti essere interessato ad aggiungere la libreria ThreeTen-Extra al tuo progetto per utilizzare la sua Interval
classe per rappresentare questa coppia di Instant
oggetti. Questo offre classe metodi utili per il confronto, come abuts
, overlaps
, contains
, e altro ancora.
Interval interval = Interval.of( start , stop ) ;
interval.toString () = 2020-01-29T06: 00: 00Z / 2020-01-30T06: 00: 00Z
Mezzo aperto
La risposta di mprivat è corretta. Il suo punto è non cercare di ottenere la fine di una giornata, ma piuttosto confrontarla con "prima dell'inizio del giorno successivo". La sua idea è nota come approccio "semiaperto" in cui un arco di tempo ha un inizio inclusivo mentre il finale è esclusivo .
- Gli attuali framework data-ora di Java (java.util.Date/Calendar e Joda-Time ) utilizzano entrambi i millisecondi dell'epoca . Ma in Java 8, le nuove classi java.time. * JSR 310 utilizzano una risoluzione in nanosecondi. Qualsiasi codice scritto in base alla forzatura del conteggio dei millisecondi dell'ultimo momento della giornata non sarebbe corretto se passato alle nuove classi.
- Il confronto dei dati da altre fonti diventa errato se utilizzano altre risoluzioni. Ad esempio, le librerie Unix in genere impiegano interi secondi e database come Postgres risolvono la data e l'ora in microsecondi.
- Alcuni cambiamenti dell'ora legale avvengono dopo mezzanotte, il che potrebbe confondere ulteriormente le cose.
Joda-Time 2.3 offre un metodo per questo scopo, per ottenere primo momento della giornata: withTimeAtStartOfDay()
. Allo stesso modo in java.time,LocalDate::atStartOfDay
.
Cerca in StackOverflow "joda half-open" per vedere ulteriori discussioni ed esempi.
Vedi questo post, Intervalli di tempo e altri intervalli dovrebbero essere semiaperti , di Bill Schneider.
Evita le classi data-ora precedenti
Le classi java.util.Date e .Calendar sono notoriamente problematiche. Evitali.
Usa le classi java.time . Il framework java.time è il successore ufficiale della libreria di grande successo Joda-Time .
java.time
Il framework java.time è integrato in Java 8 e versioni successive. Backport su Java 6 e 7 nel progetto ThreeTen-Backport , ulteriormente adattato ad Android nel ThreeTenABP progetto .
Un Instant
è un momento sulla timeline in UTC con una risoluzione di nanosecondi .
Instant instant = Instant.now();
Applica un fuso orario per ottenere l' ora dell'orologio da parete per alcune località.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
Per ottenere il primo momento della giornata, ripassa la LocalDate
lezione e il suo atStartOfDay
metodo.
ZonedDateTime zdtStart = zdt.toLocalDate().atStartOfDay( zoneId );
Usando l'approccio Half-Open, ottieni il primo momento del giorno successivo.
ZonedDateTime zdtTomorrowStart = zdtStart.plusDays( 1 );
Attualmente il framework java.time manca di una Interval
classe come descritto di seguito per Joda-Time. Tuttavia, il progetto ThreeTen-Extra estende java.time con classi aggiuntive. Questo progetto è il banco di prova per possibili future aggiunte a java.time. Tra le sue classi c'è Interval
. Costruisci un Interval
passando un paio di Instant
oggetti. Possiamo estrarre un Instant
dai nostri ZonedDateTime
oggetti.
Interval today = Interval.of( zdtStart.toInstant() , zdtTomorrowStart.toInstant() );
Informazioni su java.time
Il framework java.time è integrato in Java 8 e versioni successive. Queste classi soppiantare la vecchia fastidiosi legacy classi data-time come java.util.Date
, Calendar
, e SimpleDateFormat
.
Per saperne di più, vedere il tutorial Oracle . E cerca Stack Overflow per molti esempi e spiegazioni. La specifica è JSR 310 .
Il progetto Joda-Time , ora in modalità di manutenzione , consiglia la migrazione alle classi java.time .
Puoi scambiare oggetti java.time direttamente con il tuo database. Utilizza un driver JDBC compatibile con JDBC 4.2 o successivo. Non c'è bisogno di stringhe, non c'è bisogno di java.sql.*
classi. Hibernate 5 e JPA 2.2 supportano java.time .
Dove ottenere le classi java.time?
Joda-Time
AGGIORNAMENTO: Il progetto Joda-Time è ora in modalità di manutenzione e consiglia la migrazione alle classi java.time . Lascio questa sezione intatta per la storia.
Joda Time ha tre classi per rappresentare un arco di tempo in vari modi: Interval
, Period
, e Duration
. An Interval
ha un inizio e una fine specifici sulla linea temporale dell'Universo. Ciò corrisponde alla nostra esigenza di rappresentare "un giorno".
Chiamiamo il metodo withTimeAtStartOfDay
piuttosto che impostare l'ora del giorno su zero. A causa dell'ora legale e di altre anomalie, il primo momento della giornata potrebbe non esserlo 00:00:00
.
Codice di esempio utilizzando Joda-Time 2.3.
DateTimeZone timeZone = DateTimeZone.forID( "America/Montreal" );
DateTime now = DateTime.now( timeZone );
DateTime todayStart = now.withTimeAtStartOfDay();
DateTime tomorrowStart = now.plusDays( 1 ).withTimeAtStartOfDay();
Interval today = new Interval( todayStart, tomorrowStart );
Se è necessario, è possibile convertire in java.util.Date.
java.util.Date date = todayStart.toDate();