web-dev-qa-db-ja.com

Spark SQLはタイムゾーンを正しく変換していません

Scala 2.10.4およびspark 1.5.1およびspark 1.6

sqlContext.sql(
  """
    |select id,
    |to_date(from_utc_timestamp(from_unixtime(at), 'US/Pacific')),
    |from_utc_timestamp(from_unixtime(at), 'US/Pacific'),
    |from_unixtime(at),
    |to_date(from_unixtime(at)),
    | at
    |from events
    | limit 100
  """.stripMargin).collect().foreach(println)

Spark-Submitオプション:--driver-Java-options '-Duser.timezone=US/Pacific'

結果:

[56d2a9573bc4b5c38453eae7,2016-02-28,2016-02-27 16:01:27.0,2016-02-28 08:01:27,2016-02-28,1456646487]
[56d2aa1bfd2460183a571762,2016-02-28,2016-02-27 16:04:43.0,2016-02-28 08:04:43,2016-02-28,1456646683]
[56d2aaa9eb63bbb63456d5b5,2016-02-28,2016-02-27 16:07:05.0,2016-02-28 08:07:05,2016-02-28,1456646825]
[56d2aab15a21fa5f4c4f42a7,2016-02-28,2016-02-27 16:07:13.0,2016-02-28 08:07:13,2016-02-28,1456646833]
[56d2aac8aeeee48b74531af0,2016-02-28,2016-02-27 16:07:36.0,2016-02-28 08:07:36,2016-02-28,1456646856]
[56d2ab1d87fd3f4f72567788,2016-02-28,2016-02-27 16:09:01.0,2016-02-28 08:09:01,2016-02-28,1456646941]

US/Pacificの時間は2016-02-28 00:01:27などですが、「8」時間を2回差し引く方法もあります。

9
Gaurav Shah

しばらく読んだ後の結論は次のとおりです。

  • Spark-Sqlは日時、タイムゾーンをサポートしていません
  • タイムスタンプを使用することが唯一の解決策です
  • from_unixtime(at)は、エポック時間を正しく解析します。文字列として出力すると、タイムゾーンが原因で変更されます。 from_unixtimeは正しく変換します(印刷すると異なる結果が表示される場合があります)
  • from_utc_timestampは、タイムスタンプをそのタイムゾーンにシフトします(変換するだけではありません)。この場合、(-08:00)以降の時間から8時間差し引かれます。
  • sQLの結果を出力すると、タイムゾーンパラメータに関して時間を台無しにしてしまいます
8
Gaurav Shah

記録のために、ここでは、UDFを使用してそのようなLong値を変換します。

ここでは、タイムスタンプの日付文字列表現(UTCのエポック以降のミリ秒)のみに関心があります。

val udfToDateUTC = udf((epochMilliUTC: Long) => {
  val dateFormatter = Java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(Java.time.ZoneId.of("UTC"))
  dateFormatter.format(Java.time.Instant.ofEpochMilli(epochMilliUTC))
})

このようにして、日付の解析とレンダリングを制御します。

1
Michel Lemay