【问题标题】:Scala: Parse timestamp using spark 3.1.2Scala:使用 spark 3.1.2 解析时间戳
【发布时间】:2022-01-27 13:31:01
【问题描述】:

我有一个 Excel 阅读器,我将结果放入 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

(可点击链接: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。 我在这里错过了什么明显的东西吗?

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

【问题讨论】:

标签: scala apache-spark parsing timestamp spark3


【解决方案1】:

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

“E”、“F”、“q”和“Q”的符号只能用于日期时间格式,例如日期格式。它们不允许用于日期时间解析,例如to_timestamp。

如果您想应用 Spark 版本 spark.sql.legacy.timeParserPolicy 选项设置为 LEGACY

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

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

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")

【讨论】:

  • 非常感谢。第二个选项是我的首选,因为如果可能的话我不想更改配置。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-20
  • 1970-01-01
  • 2016-12-16
  • 2021-07-05
  • 1970-01-01
  • 2023-03-25
相关资源
最近更新 更多