Mam problemy z klasą Date w Javie. Klasa Date zwraca lokalną datę maszyny, ale potrzebuję UTC-0.
Wyszukałem w Google i znalazłem świetne rozwiązanie dla JavaScript, ale dla Javy nic przydatnego.
Jak uzyskać datę UTC + 0 w Javie 8?
Mam problemy z klasą Date w Javie. Klasa Date zwraca lokalną datę maszyny, ale potrzebuję UTC-0.
Wyszukałem w Google i znalazłem świetne rozwiązanie dla JavaScript, ale dla Javy nic przydatnego.
Jak uzyskać datę UTC + 0 w Javie 8?
Odpowiedzi:
W Javie 8 możesz pisać:
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;
OffsetDateTime
, niż ZonedDateTime
biorąc pod uwagę, że pracujemy z przesunięciem względem UTC, a nie z pełną strefą czasową?
Instant.now()
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 .
Instant instant = Instant.now();
toString
Metoda 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
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 z Instant
na OffsetDateTime
. Określ przesunięcie od czasu UTC . W java.time oznacza to ZoneOffset
obiekt. Tutaj chcemy trzymać się UTC (+00), abyśmy mogli użyć wygodnej stałej ZoneOffset.UTC
.
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC );
2016-06-27T19: 15: 25.864Z
Lub pomiń Instant
zajęcia.
OffsetDateTime.now( ZoneOffset.UTC )
Teraz, mając OffsetDateTime
obiekt w dłoni, możesz użyć go DateTimeFormatter
do tworzenia obiektów typu String z tekstem w alternatywnych formatach. Wyszukaj przepełnienie stosu dla wielu przykładów użycia DateTimeFormatter
.
ZonedDateTime
Jeśli chcesz wyświetlić zegar ścienny dla określonej strefy czasowej, zastosuj ZoneId
znak ZonedDateTime
.
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 15
niż 19
godziny. Instant
a ZonedDateTime
oba przedstawiają ten sam jednoczesny moment, oglądany tylko przez dwie różne soczewki.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );
2016-06-27T15: 15: 25.864-04: 00 [Ameryka / Montreal]
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 )
i java.util.Date::toInstant
.
java.util.Date utilDate = java.util.Date.from( instant );
I idzie w innym kierunku.
Instant instant= utilDate.toInstant();
Podobnie poszukaj nowych metod dodanych do GregorianCalendar
(podklasy Calendar
) w celu konwersji na i z java.time.ZonedDateTime
.
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
, i SimpleDateFormat
.
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?
ZonedDateTime
, nie byłby potrzebny, ponieważ wszystko ZoneId
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 .
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"));
Wrócić do Instant
Instant ins4 = Instant.from(odt);
Instant
jest to czas lokalny. Z Instant
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
Rozwiązanie 1-liniowe w Javie 8:
public Date getCurrentUtcTime() {
return Date.from(Instant.now());
}
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.