0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ScalikeJDBCで時刻を扱う際のミリ秒以下の精度

Last updated at Posted at 2020-03-24

ScalikeJDBCでSQLServerからZonedDateTimeを取り出す際に、ミリ秒以下の値がうまく取り出せない

追記
@xuwei_k さんに頂いたコメント通り、3.4.0にバージョンを上げるとZonedDateTimeで直接取得してもナノ秒精度が保たれるようになりました :pray:

検証環境

  • 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)
  }
0
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?