Konwersja pomiędzy Javą.czas.LocalDateTime i java.util.Data
Java 8 ma zupełnie nowe API dla daty i czasu. Jedną z najbardziej użytecznych klas w tym API jest LocalDateTime
, do przechowywania niezależnej od strefy czasowej daty z wartością czasu.
Prawdopodobnie są miliony linii kodu używających do tego celu klasy legacy java.util.Date
. W związku z tym, podczas łączenia Starego i nowego kodu będzie konieczna konwersja między nimi. Ponieważ wydaje się, że nie ma bezpośrednich metod, aby to osiągnąć, jak można to zrobić?
7 answers
Krótka odpowiedź:
Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
Date out = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());
Wyjaśnienie:
(na podstawie tego pytania o LocalDate
)
Pomimo swojej nazwy, java.util.Date
reprezentuje moment w linii czasowej, a nie "datę". Rzeczywiste dane przechowywane w obiekcie to long
liczba milisekund od 1970-01-01T00: 00Z (północ na początku 1970 GMT/UTC).
Jest Instant
, więc istnieją wygodne metody zapewniające konwersję do i z powrotem:
Date input = new Date();
Instant instant = input.toInstant();
Date output = Date.from(instant);
A java.util.Date
instancja nie ma pojęcia strefy czasowej. Może to wydawać się dziwne, jeśli zadzwonisz {[10] } na java.util.Date
, ponieważ {[12] } jest względem strefy czasowej. Jednak ta metoda faktycznie używa domyślnej strefy czasowej Javy w locie, aby zapewnić ciąg znaków. Strefa czasowa nie jest częścią rzeczywistego stanu java.util.Date
.
An Instant
również nie zawiera żadnych informacji o strefie czasowej. Tak więc, aby konwertować z Instant
na lokalną datę-czas, konieczne jest określenie strefy czasowej. To może być strefa domyślna - ZoneId.systemDefault()
- lub może to być Strefa czasowa, którą kontroluje aplikacja, na przykład strefa czasowa z preferencji użytkownika. Ma wygodną metodę fabryczną, która zajmuje zarówno strefę natychmiastową, jak i czasową:]}
Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
W odwrotnej kolejności, LocalDateTime
Strefa czasowa jest określona przez wywołanie metody atZone(ZoneId)
. W ten sposób można przekształcić je bezpośrednio na Instant
:
LocalDateTime ldt = ...
ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault());
Date output = Date.from(zdt.toInstant());
Zauważ, że konwersja z LocalDateTime
na {[20] } może spowodować nieoczekiwane zachowanie. Dzieje się tak dlatego, że nie każdy lokalna data-czas istnieje ze względu na czas letni. Jesienią / jesienią, istnieje nakładanie się w linii czasu lokalnego, gdzie ta sama lokalna data-czas występuje dwa razy. Wiosną jest przerwa, w której godzina znika. # Patrz Javadoc atZone(ZoneId)
więcej definicji tego, co zrobi konwersja.
Podsumowanie, jeśli podróżujesz w obie strony a java.util.Date
do a LocalDateTime
i z powrotem do a java.util.Date
możesz skończyć z innym momentem ze względu na czas letni.
DODATKOWE info: jest jeszcze różnica, która wpłynie na bardzo stare daty. java.util.Date
używa kalendarza, który datuje się na 15 października 1582, z datami wcześniejszymi, używając kalendarza juliańskiego zamiast gregoriańskiego. Z kolei java.time.*
używa systemu kalendarza ISO (równoważnego Gregoriańskiemu) dla wszystkich czasów. W większości przypadków system kalendarza ISO jest tym, czego chcesz, ale możesz zobaczyć dziwne efekty podczas porównywania dat przed rokiem 1582.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:23
Oto, co wymyśliłem (i jak wszystkie zagadki związane z datą, prawdopodobnie zostanie obalone na podstawie jakiejś dziwnej regulacji strefy czasowej-leapyear-daylight :d) {]}
Round-tripping: Date
> LocalDateTime
Podane: Date date = [some date]
(1) LocalDateTime
InstantDate
Instant instant = Instant.ofEpochMilli(date.getTime());
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
(2) Date
Instant LocalDateTime
Instant instant = ldt.toInstant(ZoneOffset.UTC);
Date date = Date.from(instant);
Przykład:
Podane:
Date date = new Date();
System.out.println(date + " long: " + date.getTime());
(1) LocalDateTime
InstantDate:
Create Instant
od Date
:
Instant instant = Instant.ofEpochMilli(date.getTime());
System.out.println("Instant from Date:\n" + instant);
Tworzenie Date
z Instant
(nie jest konieczne, ale dla ilustracji):
date = Date.from(instant);
System.out.println("Date from Instant:\n" + date + " long: " + date.getTime());
Create LocalDateTime
from Instant
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
System.out.println("LocalDateTime from Instant:\n" + ldt);
(2) Date
Instant LocalDateTime
Create Instant
from LocalDateTime
:
instant = ldt.toInstant(ZoneOffset.UTC);
System.out.println("Instant from LocalDateTime:\n" + instant);
Create Date
from Instant
:
date = Date.from(instant);
System.out.println("Date from Instant:\n" + date + " long: " + date.getTime());
Wyjście To:
Fri Nov 01 07:13:04 PDT 2013 long: 1383315184574
Instant from Date:
2013-11-01T14:13:04.574Z
Date from Instant:
Fri Nov 01 07:13:04 PDT 2013 long: 1383315184574
LocalDateTime from Instant:
2013-11-01T14:13:04.574
Instant from LocalDateTime:
2013-11-01T14:13:04.574Z
Date from Instant:
Fri Nov 01 07:13:04 PDT 2013 long: 1383315184574
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-28 22:02:47
O wiele wygodniejszy sposób, jeśli jesteś pewien, że potrzebujesz domyślnej strefy czasowej:
Date d = java.sql.Timestamp.valueOf( myLocalDateTime );
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-18 19:34:23
Poniższe rozwiązanie wydaje się działać podczas konwersji z nowego API LocalDateTime do Javy.util.data:
Date.from(ZonedDateTime.of({time as LocalDateTime}, ZoneId.systemDefault()).toInstant());
Odwrotna konwersja może być (miejmy nadzieję) osiągnięta w podobny sposób...
Mam nadzieję, że to pomoże...Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-27 08:06:10
Nie jestem pewien, czy jest to najprostszy, czy najlepszy sposób, czy są jakieś pułapki, ale to działa:
static public LocalDateTime toLdt(Date date) {
GregorianCalendar cal = new GregorianCalendar();
cal.setTime(date);
ZonedDateTime zdt = cal.toZonedDateTime();
return zdt.toLocalDateTime();
}
static public Date fromLdt(LocalDateTime ldt) {
ZonedDateTime zdt = ZonedDateTime.of(ldt, ZoneId.systemDefault());
GregorianCalendar cal = GregorianCalendar.from(zdt);
return cal.getTime();
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-17 15:40:54
Wszystko jest tutaj: http://blog.progs.be/542/date-to-java-time
ODPOWIEDŹ z "round-tripping" nie jest dokładna: kiedy robisz
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
Jeśli Strefa czasowa systemu nie jest UTC / GMT, można zmienić czas !
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-07 19:03:16
Jeśli korzystasz z Androida i używasz threetenbp możesz zamiast tego użyć DateTimeUtils
.
Ex:
Date date = DateTimeUtils.toDate(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
Nie możesz używać Date.from
, ponieważ jest on obsługiwany tylko przez api 26+
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-06 04:37:59