java.util.Datenigdy nie jest datą maszyny lokalnej. Jest zawsze definiowany jako upływające milisekundy od 1970-01-01 względem UTC + 00: 00. Być może zachowanie tej metody wprowadza w błąd toString(), ponieważ rzeczywiście używasz reprezentacji w lokalnej strefie czasowej.
OffsetDateTime utc =OffsetDateTime.now(ZoneOffset.UTC);
Aby odpowiedzieć na swój komentarz, możesz następnie przekonwertować go na datę (chyba że polegasz na starszym kodzie, nie widzę żadnego powodu) lub na milis od epok:
Date date =Date.from(utc.toInstant());long epochMillis = utc.toEpochSecond()*1000;
dzięki. czy można przekonwertować ZonedDateTime na Date lub long (ms)?
Mark
7
Chociaż kod tej odpowiedzi technicznie działa, czy nie byłoby bardziej odpowiednie użycie OffsetDateTime, niż ZonedDateTimebiorąc pod uwagę, że pracujemy z przesunięciem względem UTC, a nie z pełną strefą czasową?
Basil Bourque
179
tl; dr
Instant.now()
java.time
Kłopotliwe stare klasy daty i godziny dołączone do najwcześniejszych wersji Javy zostały zastąpione przez klasy java.time wbudowane w Javę 8 i nowsze. Zobacz samouczek Oracle . Wiele funkcji zostało przeniesionych do Java 6 i 7 w ThreeTen-Backport i dodatkowo dostosowanych do systemu Android w ThreeTenABP .
Instant
Symbol Instantreprezentuje moment na osi czasu w UTC z rozdzielczością do nanosekund .
Instant instant =Instant.now();
toStringMetoda generuje obiekt String z tekstem reprezentującego wartość data-czas, korzystając z jednego ze standardowych ISO 8601 formatach.
String output = instant.toString();
2016-06-27T19: 15: 25.864Z
InstantKlasa podstawowa klasa budynku blok w java.time. Powinna to być klasa, na którą powinieneś przejść podczas obsługi daty i godziny, ponieważ ogólnie najlepszą praktyką jest śledzenie, przechowywanie i wymiana wartości daty i czasu w UTC.
OffsetDateTime
Ale Instantma ograniczenia, takie jak brak opcji formatowania do generowania ciągów w alternatywnych formatach. Aby uzyskać większą elastyczność, przekonwertuj z Instantna OffsetDateTime. Określ przesunięcie od czasu UTC . W java.time oznacza to ZoneOffsetobiekt. Tutaj chcemy trzymać się UTC (+00), abyśmy mogli użyć wygodnej stałej ZoneOffset.UTC.
Teraz, mając OffsetDateTimeobiekt w dłoni, możesz użyć go DateTimeFormatterdo tworzenia obiektów typu String z tekstem w alternatywnych formatach. Wyszukaj przepełnienie stosu dla wielu przykładów użycia DateTimeFormatter.
W tym przykładzie stosujemy strefę czasową Montréal. Latem, pod nonsensem czasu letniego (DST) , strefa ma przesunięcie -04:00. Zwróć więc uwagę, że pora dnia jest o cztery godziny wcześniejsza 15niż 19godziny. Instanta ZonedDateTimeoba przedstawiają ten sam jednoczesny moment, oglądany tylko przez dwie różne soczewki.
ZoneId z =ZoneId.of("America/Montreal");ZonedDateTime zdt = instant.atZone( z );
Możesz wymieniać obiekty java.time bezpośrednio ze swoją bazą danych. Użyj sterownika JDBC zgodnego z JDBC 4.2 lub nowszym. Nie ma potrzeby stosowania ciągów ani java.sql.*klas. Hibernate 5 i JPA 2.2 obsługują java.time .
więc gdyby czas letni nie istniał ZonedDateTime, nie byłby potrzebny, ponieważ wszystko ZoneIdbyłoby mapowane na taki, ZoneOffsetktórego moglibyśmy po prostu użyć OffsetDateTime?
wilmol
1
@wilmol Nie. Czas letni (DST) to tylko jeden z wielu powodów, dla których politycy decydują się na przedefiniowanie granic stref czasowych i przesunięć w tych strefach. Niedawno Korea Północna zmieniła swój zegar o pół godziny, aby zsynchronizować się z Koreą Południową z powodów dyplomatycznych. Podczas wojny najeźdźcy / okupanci mogą zmienić przesunięcie, aby dopasować je do kraju ojczystego. Obecnie pojawia się nowa moda, w której rządy decydują się zatrzymać zmiany czasu letniego, ale na stałe pozostają na nim, zamiast powracać do poprzedniego standardowego czasu. Zawsze planuj przesunięcie każdej zmiany strefy lub Twoja aplikacja w końcu się zepsuje.
Basil Bourque,
1
Fantastyczna odpowiedź! Naprawdę doceniam czas, jaki w to włożyłeś. :)
drognisep
ZoneId.of („Ameryka / Montreal”); po co ktoś miałby wymyślać coś takiego w jdk? jest brzydki, obrzydliwy, nie mówi, czy coś jest nie tak przed uruchomieniem, kto pamięta cały ten twardy kod? dlaczego nie umieścić tego w klasie ENUM?
workplaylifecycle
4
W java8 użyłbym Instantklasy, która jest już w UTC i jest wygodna w obsłudze .
import java.time.Instant;Instant ins =Instant.now();long ts = ins.toEpochMilli();Instant ins2 =Instant.ofEpochMilli(ts)
Alternatywnie możesz skorzystać z:
import java.time.*;Instant ins =Instant.now();OffsetDateTime odt = ins.atOffset(ZoneOffset.UTC);ZonedDateTime zdt = ins.atZone(ZoneId.of("UTC"));
Nie, nieInstant jest to czas lokalny. Z Instantdefinicji jest to UTC. Więc nie ma potrzeby, aby machinacje widoczne w tej odpowiedzi próbowały dostać się do UTC; Instantjuż jest w UTC. Zobacz moją odpowiedź, aby uzyskać więcej informacji i znacznie prostszy kod.
java.util.Date
nigdy nie jest datą maszyny lokalnej. Jest zawsze definiowany jako upływające milisekundy od 1970-01-01 względem UTC + 00: 00. Być może zachowanie tej metody wprowadza w błądtoString()
, ponieważ rzeczywiście używasz reprezentacji w lokalnej strefie czasowej.Odpowiedzi:
W Javie 8 możesz pisać:
Aby odpowiedzieć na swój komentarz, możesz następnie przekonwertować go na datę (chyba że polegasz na starszym kodzie, nie widzę żadnego powodu) lub na milis od epok:
źródło
OffsetDateTime
, niżZonedDateTime
biorąc pod uwagę, że pracujemy z przesunięciem względem UTC, a nie z pełną strefą czasową?tl; dr
java.time
Kłopotliwe stare klasy daty i godziny dołączone do najwcześniejszych wersji Javy zostały zastąpione przez klasy java.time wbudowane w Javę 8 i nowsze. Zobacz samouczek Oracle . Wiele funkcji zostało przeniesionych do Java 6 i 7 w ThreeTen-Backport i dodatkowo dostosowanych do systemu Android w ThreeTenABP .
Instant
Symbol
Instant
reprezentuje moment na osi czasu w UTC z rozdzielczością do nanosekund .toString
Metoda generuje obiekt String z tekstem reprezentującego wartość data-czas, korzystając z jednego ze standardowych ISO 8601 formatach.Instant
Klasa podstawowa klasa budynku blok w java.time. Powinna to być klasa, na którą powinieneś przejść podczas obsługi daty i godziny, ponieważ ogólnie najlepszą praktyką jest śledzenie, przechowywanie i wymiana wartości daty i czasu w UTC.OffsetDateTime
Ale
Instant
ma ograniczenia, takie jak brak opcji formatowania do generowania ciągów w alternatywnych formatach. Aby uzyskać większą elastyczność, przekonwertuj zInstant
naOffsetDateTime
. Określ przesunięcie od czasu UTC . W java.time oznacza toZoneOffset
obiekt. Tutaj chcemy trzymać się UTC (+00), abyśmy mogli użyć wygodnej stałejZoneOffset.UTC
.Lub pomiń
Instant
zajęcia.Teraz, mając
OffsetDateTime
obiekt w dłoni, możesz użyć goDateTimeFormatter
do tworzenia obiektów typu String z tekstem w alternatywnych formatach. Wyszukaj przepełnienie stosu dla wielu przykładów użyciaDateTimeFormatter
.ZonedDateTime
Jeśli chcesz wyświetlić zegar ścienny dla określonej strefy czasowej, zastosuj
ZoneId
znakZonedDateTime
.W tym przykładzie stosujemy strefę czasową Montréal. Latem, pod nonsensem czasu letniego (DST) , strefa ma przesunięcie
-04:00
. Zwróć więc uwagę, że pora dnia jest o cztery godziny wcześniejsza15
niż19
godziny.Instant
aZonedDateTime
oba przedstawiają ten sam jednoczesny moment, oglądany tylko przez dwie różne soczewki.Konwersja
Chociaż powinieneś unikać starych klas daty i godziny, jeśli musisz, możesz konwertować przy użyciu nowych metod dodanych do starych klas. Tutaj używamy
java.util.Date.from( Instant )
ijava.util.Date::toInstant
.I idzie w innym kierunku.
Podobnie poszukaj nowych metod dodanych do
GregorianCalendar
(podklasyCalendar
) w celu konwersji na i zjava.time.ZonedDateTime
.Informacje o java.time
Struktura java.time jest wbudowana w Javę 8 i nowsze. Klasy te kłopotliwe zastąpić stary starszych klas Date-Time, takich jak
java.util.Date
,Calendar
, iSimpleDateFormat
.Aby dowiedzieć się więcej, zobacz samouczek Oracle . I przeszukaj Stack Overflow, aby znaleźć wiele przykładów i wyjaśnień. Specyfikacja to JSR 310 .
Projekt Joda-Time , obecnie w trybie konserwacji , zaleca migrację do klas java.time .
Możesz wymieniać obiekty java.time bezpośrednio ze swoją bazą danych. Użyj sterownika JDBC zgodnego z JDBC 4.2 lub nowszym. Nie ma potrzeby stosowania ciągów ani
java.sql.*
klas. Hibernate 5 i JPA 2.2 obsługują java.time .Skąd wziąć klasy java.time?
źródło
ZonedDateTime
, nie byłby potrzebny, ponieważ wszystkoZoneId
byłoby mapowane na taki,ZoneOffset
którego moglibyśmy po prostu użyćOffsetDateTime
?W java8 użyłbym
Instant
klasy, która jest już w UTC i jest wygodna w obsłudze .Alternatywnie możesz skorzystać z:
Wrócić do
Instant
źródło
Instant
jest to czas lokalny. ZInstant
definicji jest to UTC. Więc nie ma potrzeby, aby machinacje widoczne w tej odpowiedzi próbowały dostać się do UTC;Instant
już jest w UTC. Zobacz moją odpowiedź, aby uzyskać więcej informacji i znacznie prostszy kod.W Java8 używasz nowego interfejsu API czasu i konwertujesz natychmiastową in na ZonedDateTime przy użyciu strefy czasowej UTC
źródło
Rozwiązanie 1-liniowe w Javie 8:
źródło