ScalikeJDBCでSQLServerからZonedDateTimeを取り出す際に、ミリ秒以下の値がうまく取り出せない
追記
@xuwei_k さんに頂いたコメント通り、3.4.0にバージョンを上げるとZonedDateTimeで直接取得してもナノ秒精度が保たれるようになりました
検証環境
- Scala
- 2.12.10
- JDK
- OpenJDK 8
- ScalikeJDBC
- 3.3.1
- JDBC
- mssql-jdbc 7.2.1.jre8
- SQLServer
- 2017-GA
SQLServerでの時刻は datetimeoffset(7)
を使用しているので100ナノ秒の精度で扱いたい
調査
ZonedDateTimeを入れる
100ナノ秒精度、JSTの値を扱う
val date: ZonedDateTime = ZonedDateTime.parse("2019-09-05T12:34:56.1234567+09:00")
DBにも100ナノ秒の精度で保存される。
2019-09-05 12:34:56.1234567 +09:00
ZonedDateTimeで取り出す
def * : WrappedResultSet => ZonedDateTime =
(set: WrappedResultSet) => set.zonedDateTime(columnName)
ミリ秒以下が落ちてしまう。
2019-09-06T12:34:56.123+09:00[Asia/Tokyo]
ZonedDateTimeで取り出す その2
別メソッドで取り出してみる
def * : WrappedResultSet => ZonedDateTime =
(set: WrappedResultSet) => set.dateTime(columnName)
同様にミリ秒以下が落ちてしまう。
2019-09-06T12:34:56.123+09:00[Asia/Tokyo]
TimeStampで取り出す
def * : WrappedResultSet => Timestamp =
(set: WrappedResultSet) => set.timestamp(columnName)
ナノ秒まで取り出せる。
2019-09-06 12:34:56.1234567
が、タイムゾーンは取得できない。
OffsetDateTimeで取り出す
def * : WrappedResultSet => OffsetDateTime =
(set: WrappedResultSet) => set.offsetDateTime(columnName)
ミリ秒以下が落ちてしまう。
2019-09-06T12:34:56.123+09:00
LocalDateTimeで取り出す
def * : WrappedResultSet => LocalDateTime =
(set: WrappedResultSet) => set.localDateTime(columnName)
ミリ秒以下が落ちてしまう。
2019-09-06T12:34:56.123
Stringで取り出す
def * : WrappedResultSet => String =
(set: WrappedResultSet) => set.string(columnName)
ナノ秒まで取り出せる。
2019-09-06 12:34:56.1234567 +09:00
が、そのままZonedDateTimeにパースさせることはできない.
結論
Java 8では一部の時刻型の精度が低い様子。
java 9以上に上げると解決するかも?
rf: https://github.com/h2database/h2database/issues/1178#issuecomment-397500855
ということで、Java 8ではStringで取り出し、フォーマットを指定してZonedDateTimeにパースするのが確実っぽい。
def fromSqlServer(date: String): ZonedDateTime = {
val format = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSSSSSS xxxxx")
ZonedDateTime.parse(date, format)
}