![](/img/trans.png)
[英]Converting java.util.Date to java.time.LocalDateTime using ZoneId.systemDefault()
[英]Converting between java.time.LocalDateTime and java.util.Date
Java 8 有一個全新的日期和時間 API。 此 API 中最有用的類之一是LocalDateTime
,用於保存與時區無關的日期時間值。
為此,可能有數百萬行代碼使用遺留類java.util.Date
。 因此,當連接新舊代碼時,需要在兩者之間進行轉換。 由於似乎沒有直接的方法來實現這一點,如何做到這一點?
簡短的回答:
Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
Date out = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());
盡管它的名字, java.util.Date
代表時間線上的一個瞬間,而不是“日期”。 對象中存儲的實際數據是自 1970-01-01T00:00Z(格林威治標准時間 1970/UTC 開始時的午夜)以來的long
計數。
JSR-310 java.util.Date
的等效類是Instant
,因此有方便的方法來提供來回轉換:
Date input = new Date();
Instant instant = input.toInstant();
Date output = Date.from(instant);
java.util.Date
實例沒有時區的概念。 如果您在java.util.Date
上調用toString()
,這可能看起來很奇怪,因為toString
是相對於時區的。 然而,該方法實際上使用 Java 的默認時區即時提供字符串。 時區不是java.util.Date
的實際狀態的一部分。
Instant
也不包含有關時區的任何信息。 因此,要將Instant
轉換為本地日期時間,必須指定時區。 這可能是默認區域 - ZoneId.systemDefault()
- 或者它可能是您的應用程序控制的時區,例如來自用戶首選項的時區。 LocalDateTime
有一個方便的工廠方法,可以同時使用即時和時區:
Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
相反,時區的LocalDateTime
是通過調用atZone(ZoneId)
方法指定的。 ZonedDateTime
然后可以直接轉換為Instant
:
LocalDateTime ldt = ...
ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault());
Date output = Date.from(zdt.toInstant());
請注意,從LocalDateTime
到ZonedDateTime
的轉換可能會引入意外行為。 這是因為由於夏令時,並非每個本地日期時間都存在。 在秋季/秋季,本地時間線重疊,同一本地日期時間出現兩次。 在春天,有一個缺口,一個小時消失了。 有關轉換將執行的操作的更多定義,請參閱atZone(ZoneId)
的 Javadoc。
總結,如果您將java.util.Date
往返到LocalDateTime
並返回到java.util.Date
,由於夏令時,您最終可能會得到不同的時刻。
附加信息:還有另一個差異會影響非常舊的日期。 java.util.Date
使用在 1582 年 10 月 15 日更改的日歷,在此之前的日期使用儒略歷而不是公歷。 相比之下, java.time.*
使用 ISO 日歷系統(相當於公歷)。 在大多數用例中,ISO 日歷系統正是您想要的,但在比較 1582 年之前的日期時,您可能會看到奇怪的效果。
這是我想出的(和所有日期時間難題一樣,它可能會根據一些奇怪的時區-閏年-日光調整而被否定:D)
Date
<<->> LocalDateTime
鑒於: Date date = [some date]
(1) LocalDateTime
<< Instant
<< Date
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);
例子:
Date date = new Date();
System.out.println(date + " long: " + date.getTime());
LocalDateTime
<< Instant
<< Date
: 從Date
創建Instant
:
Instant instant = Instant.ofEpochMilli(date.getTime());
System.out.println("Instant from Date:\n" + instant);
從Instant
創建Date
(不是必需的,但為了說明):
date = Date.from(instant);
System.out.println("Date from Instant:\n" + date + " long: " + date.getTime());
從Instant
創建LocalDateTime
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
System.out.println("LocalDateTime from Instant:\n" + ldt);
Date
<< Instant
<< LocalDateTime
從LocalDateTime
創建Instant
:
instant = ldt.toInstant(ZoneOffset.UTC);
System.out.println("Instant from LocalDateTime:\n" + instant);
從Instant
創建Date
:
date = Date.from(instant);
System.out.println("Date from Instant:\n" + date + " long: " + date.getTime());
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
如果您確定需要默認時區,則使用更方便的方法:
Date d = java.sql.Timestamp.valueOf( myLocalDateTime );
LocalDateTime
-> Date
的最快方法是:
Date.from(ldt.toInstant(ZoneOffset.UTC))
從新的 API LocalDateTime 轉換為 java.util.date 時,以下內容似乎有效:
Date.from(ZonedDateTime.of({time as LocalDateTime}, ZoneId.systemDefault()).toInstant());
可以(希望)以類似的方式實現反向轉換......
希望能幫助到你...
如果您使用的是 android 並使用Threetenbp ,則可以改用DateTimeUtils
。
前任:
Date date = DateTimeUtils.toDate(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
您不能使用Date.from
因為它僅在 api 26+ 上受支持
一切都在這里: http : //blog.progs.be/542/date-to-java-time
“往返”的答案並不准確:當你這樣做時
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
如果您的系統時區不是 UTC/GMT,請更改時間!
我不確定這是最簡單還是最好的方法,或者是否有任何陷阱,但它有效:
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();
}
我認為以下方法將在不考慮時區的情況下解決轉換問題。 如果有任何陷阱,請發表評論。
LocalDateTime datetime //input
public static final DateTimeFormatter yyyyMMddHHmmss_DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formatDateTime = datetime.format(yyyyMMddHHmmss_DATE_FORMAT);
Date outputDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(formatDateTime); //output
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.