[英]How to convert UTC DateTime to another Time Zone using Java 8 library?
[英]MySql datetime is not stored as UTC, but in server time zone
Mysql數據庫:將Java Date存儲到datetime類型的數據庫列中,例如,
Table Foo
id time
---------------------
bigint(20) datetime
日期是
01/15/19 19:00:00 (Time Zone: UTC+1:00),
DateFormat df = new SimpleDateFormat('MM/dd/yy HH:mm:ss');
df.setTimeZone("Europe/Paris"); // UTC+1:00
Date date = df.parse("01/15/19 19:00:00");
PreparedStatement st = new PreparedStatement("insert into Foo (id, time) values (?, ?)";
st.setObject(1, 1);
st.setObject(2, date);
st.executeUpdate();
預計將被轉換成
01/15/19 18:00:00 UTC
並存儲在數據庫中。
MySql時區是SYSTEM(UTC-6:00)。 JVM時區為UTC-6:00。 兩者都在同一台計算機上運行。 存儲的值為01/15/19 12:00:00。 為什么將其存儲在服務器時區(而不是UTC)中?
從Foo中選擇時間;
time
-------------------
2019-01-15 12:00:00
更改服務器時區不會影響選擇值。
mysql> set time_zone='+8:00';
select time from Foo;
time
-------------------
2019-01-15 12:00:00
使用現代的java.time類,切勿使用java.util.Date
或java.sql.Date
或java.sql.Timestamp
。
myPreparedStatement // With JDBC 4.2, wa can directly exchange java.time objects with the database.
.setObject( // Pass a `OffsetDateTime` object representing the moment we want stored in the database.
LocalDateTime.parse( // Parse the input string lacking an indicator of offset or zone.
"2019-01-19T19:00" // When using strings in standard ISO 8601 format, no need to specify a formatting pattern.
) // Returns a `LocalDateTime`, an ambiguous value without real meaning.
.atZone( // Apply a time zone to give meaning to the `LocalDateTime`.
ZoneId.of( "Europe/Paris" ) // Here we are saying "the 7 PM on that date as seen on the clock on the wall of someone standing in Paris France".
) // Returns a `ZonedDateTime` object.
.toOffsetDateTime() // Returns an `OffsetDateTime` object as demanded by the JDBC spec, stripping off the time zone to leave on the hours-minutes-seconds from UTC.
)
您使用的是可怕的日期時間類,而該類早在幾年前就被java.time類所取代。 嘗試調試/理解遺留類確實沒有任何意義,因為遺留的類很糟糕。
LocalDateTime
將您的輸入字符串解析為LocalDateTime
因為它缺少任何時區或從UTC偏移的指示。
養成盡可能在日期時間文本中使用標准ISO 8601格式的習慣。 對於帶有日期的日期,則為YYYY-MM-DDTHH:MM:SS,其中T
將日期部分與時間部分分開。
String input = "2019-01-19T19:00" ;
LocalDateTime ldt = LocalDateTime.parse( input ) ; // No need to specify formatting pattern when using standard ISO 8601 formats.
ZonedDateTime
LocalDateTime
類也缺少區域或偏移量的任何概念。 因此,此類的對象不能表示時刻, 也不是時間軸上的一點。 它代表了全球各個時區大約26-27小時的潛在時刻。
您似乎肯定知道此日期和時間旨在表示特定時區中的時刻。 因此,請應用一個時區,以使我們含糊的LocalDateTime
對象有意義。
以Continent/Region
的格式指定正確的時區名稱 ,例如America/Montreal
, Africa/Casablanca
或Pacific/Auckland
。 切勿使用2-4字母的縮寫,例如EST
或IST
因為它們不是真實的時區,不是標准化的,甚至不是唯一的(!)。
ZoneId z = ZoneId.of( "Europe/Paris" ) ;
如果要使用JVM的當前默認時區,請提出要求並作為參數傳遞。 如果省略,代碼將變得難以理解,因為我們不確定您是否打算使用默認值,或者您是否像許多程序員一樣不知道該問題。
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
現在我們可以應用ZoneId
來獲取ZonedDateTime
。
ZonedDateTime zdt = ldt.atZone( z ) ;
OffsetDateTime
您的JDBC 可以接受ZonedDateTime
對象,但是JDBC 4.2規范要求它采用OffsetDateTime
。 有什么不同? ZonedDateTime
和OffsetDateTime
表示時刻,即時間軸上的一點。 偏移量只是UTC之前或之后的數小時-數分鍾-秒。 時區更多。 時區是特定區域的人們過去,現在和將來對偏移量的更改的歷史記錄。 因此,時區始終是可取的。 除了這里,在我們使用JDBC與數據庫交換java.time對象的地方,我們使用OffsetDateTime
編寫標准代碼。
OffsetDateTime odt = zdt.toOffsetDateTime() ; // Convert from moment with time zone to a moment with merely an offset-from-UTC.
現在,我們可以將這一刻傳遞給您准備好的聲明。
myPreparedStatement( … , odt ) ; // Pass a `OffsetDateTime` moment as the value for a placeholder in the SQL of your prepared statement.
恢復。
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
分配所需的時區。
ZoneId z = ZoneId.of( "Europe/Paris" ) ;
ZonedDateTime zdt = odt.atZone( z ) ;
在上面幾行中看到的odt
和zdt
都表示相同的同時時刻,時間軸上的相同點。 只有它們的掛鍾時間有所不同,因為大多數數據庫在您想查看巴黎時間時都存儲和檢索UTC。
java.time框架內置於Java 8及更高版本中。 這些類取代了麻煩的舊的舊式日期時間類,例如java.util.Date
, Calendar
和SimpleDateFormat
。
現在處於維護模式的Joda-Time項目建議遷移到java.time類。
要了解更多信息,請參見Oracle教程 。 並在Stack Overflow中搜索許多示例和說明。 規格為JSR 310 。
您可以直接與數據庫交換java.time對象。 使用與JDBC 4.2或更高版本兼容的JDBC驅動程序 。 不需要字符串,不需要java.sql.*
類。
在哪里獲取java.time類?
ThreeTen-Extra項目使用其他類擴展了java.time。 該項目為將來可能在java.time中添加內容提供了一個試驗場。 您可以在這里找到一些有用的類,比如Interval
, YearWeek
, YearQuarter
,和更多 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.