Spark Strutured Streaming自动将时间戳转换为本地时间

我有UTC和ISO8601的时间戳,但使用结构化流,它会自动转换为本地时间。 有没有办法阻止这种转换? 我想在UTC中使用它。

我正在从Kafka读取json数据,然后使用from_json Spark函数解析它们。

输入:

 {"Timestamp":"2015-01-01T00:00:06.222Z"} 

流:

 SparkSession .builder() .master("local[*]") .appName("my-app") .getOrCreate() .readStream() .format("kafka") ... //some magic .writeStream() .format("console") .start() .awaitTermination(); 

架构:

 StructType schema = DataTypes.createStructType(new StructField[] { DataTypes.createStructField("Timestamp", DataTypes.TimestampType, true),}); 

输出:

 +--------------------+ | Timestamp| +--------------------+ |2015-01-01 01:00:...| |2015-01-01 01:00:...| +--------------------+ 

如您所见,小时数自行增加。

PS:我试着尝试使用from_utc_timestamp Spark函数,但没有运气。

对我来说它起作用了:

 spark.conf.set("spark.sql.session.timeZone", "UTC") 

它告诉spark SQL使用UTC作为时间戳的默认时区。 我在spark SQL中使用它,例如:

 select *, cast('2017-01-01 10:10:10' as timestamp) from someTable 

我知道它在2.0.1中不起作用。 但适用于Spark 2.2。 我也在SQLTransformer使用过它。

我不确定流媒体。

注意

这个答案主要用于Spark <2.2。 对于较新的Spark版本,请参阅astro-asz 的答案

TL; DR不幸的是,这就是Spark现在处理时间戳的方式,除了直接在纪元时间运行之外,没有使用日期/时间工具,实际上没有内置的替代方案。

您可以对Spark开发人员列表进行深入的讨论: SQL TIMESTAMP语义与SPARK-18350

到目前为止,我发现最干净的解决方法是将驱动程序和执行程序的-Duser.timezone设置为UTC 。 例如,提交:

 bin/spark-shell --conf "spark.driver.extraJavaOptions=-Duser.timezone=UTC" \ --conf "spark.executor.extraJavaOptions=-Duser.timezone=UTC" 

或者通过调整配置文件( spark-defaults.conf ):

 spark.driver.extraJavaOptions -Duser.timezone=UTC spark.executor.extraJavaOptions -Duser.timezone=UTC