[英]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之外,還有什么更干凈的方法嗎?
您沒有提供足夠的信息。 報告:
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
對象傳遞給數據庫即可。
僅供參考,舊的日期時間類( Date
和Calendar
等)和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
字符串末尾的Z
是Zulu
縮寫,表示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 8及更高版本中。 這些類取代了麻煩的舊的舊式日期時間類,例如java.util.Date
, Calendar
和SimpleDateFormat
。
現在處於維護模式的Joda-Time項目建議遷移到java.time類。
要了解更多信息,請參見Oracle教程 。 並在Stack Overflow中搜索許多示例和說明。 規格為JSR 310 。
在哪里獲取java.time類?
ThreeTen-Extra項目使用其他類擴展了java.time。 該項目為將來可能在java.time中添加內容提供了一個試驗場。 您可以在這里找到一些有用的類,比如Interval
, YearWeek
, YearQuarter
,和更多 。
通過網絡傳輸和保存日期的最佳方法是以時間戳的形式(以毫秒為單位的日期),該時間戳不需要任何時區信息。 但是,在以時間戳記的形式獲取日期之后,請使用它創建日期對象。如果要以UTC格式顯示日期,則只需要對其進行轉換。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.