簡體   English   中英

如何將本地dateTime對象轉換為UTC java.util.Date

[英]How to convert a local dateTime Object to a UTC java.util.Date

我很清楚java.util.Date沒有時區,為什么會這樣。

我有一個應用程序,用戶在其中設置了自己的TimeZone,當他在DateTime選擇器中選擇Date時,該組件將Date對象返回給我。 然后,我需要修改日期以將UTC等效項保存在數據庫中。

使用org.joda.time獲取代表本地時區的UTC日期的Date對象非常簡單:

public static final Date getTimeZoneDependantDate(Date pDateUtc, String pUserTimezoneValue) {
    // Build the DateTime Object
    DateTime originalDate = new DateTime(pDateUtc.getTime(), DateTimeZone.forID(PREF_TIMEZONE_DEF_VALUE));
    // Convert the Date
    DateTime convertedDate  = originalDate.withZone(DateTimeZone.forID(pUserTimezoneValue));
    // Return the localTime associated with the timeZone
    return convertedDate.toLocalDateTime().toDate();
}

但是我堅持如何做相反的事情,將用戶選擇的日期(從他的時區角度)更改為UTC。 由於LocalDateTime將即時而不是本地Date作為參數。

除了解析String之外,還有什么更干凈的方法嗎?

tl; dr

您沒有提供足夠的信息。 報告:

  • 結果如下: myJavaUtilDate.toInstant().toString()
  • 組件的輸入
  • 應用程序的當前默認時區

細節

您實際上並未提供有關您的問題的足夠信息。 您是否通過GUI組件中的java.util.Date對象在UTC中獲取了正確的日期時間值?

如果位於America/Montreal魁北克時區的用戶在2016年12月1日輸入9 AM,並且您的組件在生成java.util.Date對象時正確地將這些值調整為UTC ,那么您就沒有問題。 對於UTC,UTC值為下午2點,因為America/Montreal在該特定日期比UTC落后5個小時。 轉換為java.sql.Timestamp對象后,只需將Date對象傳遞給數據庫即可。

僅供參考,舊的日期時間類( DateCalendar等)和Joda-Time現在都被java.time類取代了。 這是java.time中的一些示例代碼,顯示了您的組件希望采用的行為類型。

LocalDate ld = LocalDate.of ( 2016 , Month.DECEMBER , 1 );
LocalTime lt = LocalTime.of ( 9 , 0 );
ZoneId z = ZoneId.of ( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.of ( ld , lt , z );
Instant instant = zdt.toInstant (); // UTC

System.out.println ( "zdt.toString(): " + zdt );
System.out.println ( "instant.toString(): " + instant );

zdt.toString():2016-12-01T09:00-05:00 [美國/蒙特利爾]

Instant.toString():2016-12-01T14:00:00Z

字符串末尾的ZZulu縮寫,表示UTC。

鑒於java.util.Date::toString在生成字符串時應用當前默認時區的不幸行為,建議您將Date轉換為Instant以便清楚地了解其值。

Instant instantConvertedFromDateOfComponent = myJavaUtilDate.toInstant();

如果在此步驟之后您確實確實看到下午2點,那么一切都很好,並且您的組件運行良好。

如果您的組件運行狀況不佳,忽略時區問題,並像用戶希望將UTC作為自己的時區一樣報告用戶的輸入,那么您將看到2016-12-01T09:00:00Z 那是個問題。 解決方法是自行進行時區調整。 提取“本地”(無區域)值,然后應用預期的時區。

要獲取“本地”日期和時間,請首先轉換為OffsetDateTime對象。

OffsetDateTime odt = instantConvertedFromDateOfComponent.atOffset( ZoneOffset.UTC );
LocalDateTime ldt = odt.toLocalDateTime();  // 2016-12-01T09:00:00Z
ZonedDateTime zdt = ldt.atZone( z );  // 2016-12-01T09:00-05:00[America/Montreal]

如果您的JDBC驅動程序符合JDBC 4.2或更高版本,則可以直接傳遞這些java.time類型。 如果不是,則通過添加到舊類中的新方法轉換為java.sql類型。 有關堆棧溢出的討論已經很多次了,所以搜索更多信息。

服務器的當前默認時區應與您的編程無關。 始終在可選參數中明確指定所需/期望的時區,而不是隱式依賴默認值。


關於java.time

java.time框架內置於Java 8及更高版本中。 這些類取代了麻煩的舊的舊式日期時間類,例如java.util.DateCalendarSimpleDateFormat

現在處於維護模式Joda-Time項目建議遷移到java.time類。

要了解更多信息,請參見Oracle教程 並在Stack Overflow中搜索許多示例和說明。 規格為JSR 310

在哪里獲取java.time類?

  • Java SE 8SE 9及更高版本
    • 內置的
    • 標准Java API的一部分,具有捆綁的實現。
    • Java 9添加了一些次要功能和修復。
  • Java SE 6SE 7
    • java.time的許多功能在ThreeTen- Backport中都被反向移植到Java 6和7。
  • 安卓系統

ThreeTen-Extra項目使用其他類擴展了java.time。 該項目為將來可能在java.time中添加內容提供了一個試驗場。 您可以在這里找到一些有用的類,比如IntervalYearWeekYearQuarter ,和更多

通過網絡傳輸和保存日期的最佳方法是以時間戳的形式(以毫秒為單位的日期),該時間戳不需要任何時區信息。 但是,在以時間戳記的形式獲取日期之后,請使用它創建日期對象。如果要以UTC格式顯示日期,則只需要對其進行轉換。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM