Scala:使用 spark 3.1.2 解析时间戳

Scala: Parse timestamp using spark 3.1.2

我有一个 Excel-reader,我将结果放在 sparks 数据帧中。我在解析时间戳时遇到问题。

我有像 Wed Dec 08 10:49:59 CET 2021 这样的字符串形式的时间戳。我使用的是 spark-sql 版本 2.4.5 并且一切正常,直到我最近更新到版本 3.1.2.

请在下面找到一些最少的代码。

import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.functions.{col, to_timestamp}

val ts: String = "Wed Dec 08 20:49:59 CET 2021"
val oldfmt: String = "E MMM dd HH:mm:ss z yyyy"

val ttdf = Seq(ts)
  .toDF("theTimestampColumn")
  .withColumn("parsedTime", to_timestamp(col("theTimestampColumn"), fmt = oldfmt))

ttdf.show()

运行 spark 版本 2.4.5 的代码按预期工作并产生以下输出:

+--------------------+-------------------+
|  theTimestampColumn|         parsedTime|
+--------------------+-------------------+
|Wed Dec 08 20:49:...|2021-12-08 20:49:59|
+--------------------+-------------------+

现在,仅使用 spark 版本 3.1.2 执行相同的代码会导致以下错误:

Exception in thread "main" org.apache.spark.SparkUpgradeException: 
You may get a different result due to the upgrading of Spark 3.0: 
Fail to recognize 'E MMM dd HH:mm:ss z yyyy' pattern in the DateTimeFormatter. 
1) You can set spark.sql.legacy.timeParserPolicy to LEGACY to restore the behavior before Spark 3.0. 
2) You can form a valid datetime pattern with the guide from https://spark.apache.org/docs/latest/sql-ref-datetime-pattern.html

(可点击 link: https://spark.apache.org/docs/latest/sql-ref-datetime-pattern.html)

这个网站对我没有进一步的帮助。我在我的格式字符串中没有发现任何错误。 符号 Eday-of-week 表示为类似于 Tue; Tuesday 的文本。 符号 M 代表 month-of-year 就像 7; 07; Jul; July。符号 H,m,s,y 分别表示小时、分钟、秒或年。符号 z 表示 time-zone name 类似于 Pacific Standard Time; PST。 我在这里错过了一些明显的东西吗?

任何帮助将不胜感激。提前谢谢你。

您只能将 E 用于日期时间格式,而不能用于解析,如 datetime pattern documentation:

中所述

Symbols of ‘E’, ‘F’, ‘q’ and ‘Q’ can only be used for datetime formatting, e.g. date_format. They are not allowed used for datetime parsing, e.g. to_timestamp.

如果您想应用 Spark <3.0 版本的行为,您可以将 spark.sql.legacy.timeParserPolicy 选项设置为 LEGACY:

sparkSession.conf.set("spark.sql.legacy.timeParserPolicy", "LEGACY")

如果你不想改变spark配置,你可以用substr SQL函数去掉代表天的字符:

import org.apache.spark.sql.functions.{col, to_timestamp, expr}

val ts: String = "Wed Dec 08 20:49:59 CET 2021"
val fmt: String = "MMM dd HH:mm:ss z yyyy"

val ttdf = Seq(ts)
  .toDF("theTimestampColumn")
  .withColumn("preparedTimestamp", expr("substr(theTimestampColumn, 5, length(theTimestampColumn))"))
  .withColumn("parsedTime", to_timestamp(col("preparedTimestamp"), fmt = fmt))
  .drop("preparedTimestamp")