【问题标题】:Converting TZ timestamp string to a given format in UTC using spark and scala使用 spark 和 scala 将 TZ 时间戳字符串转换为 UTC 中的给定格式
【发布时间】:2019-11-29 12:05:57
【问题描述】:

我有一个名为 lastModified 的列,其字符串如下所示,表示 GMT 时间。 “2019-06-24T15:36:16.000Z”

我想使用 scala 在 spark 中将此字符串格式化为 yyyy-MM-dd HH:mm:ss 格式。为此,我创建了一个带有新列 "ConvertedTS" 的数据框。 这给出了错误的时间。

我运行它的机器位于美国/纽约时区。

df.withColumn("ConvertedTS", date_format(to_utc_timestamp(to_timestamp(col("lastModified"), "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"), "America/New_York"), "yyyy-MM-dd HH:MM:SS").cast(StringType))

我基本上是在 yyyy-MM-dd HH:mm:ss 中寻找格式化以下语句的结果

df.withColumn("LastModifiedTS", col("lastModified"))

目前对我有用的一种方法是 udf,但由于不推荐使用 udf,我一直在寻找更多可以使用的直接表达式。

val convertToTimestamp = (logTimestamp: String) => {
    println("logTimeStamp: " + logTimestamp)
    var newDate = ""
    try {
      val sourceFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX")
      sourceFormat.setTimeZone(TimeZone.getTimeZone("GMT"))
      val convertedDate = sourceFormat.parse(logTimestamp)
      val destFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
      destFormat.setTimeZone(TimeZone.getTimeZone("GMT"))
      newDate = destFormat.format(convertedDate)
      println("newDate: " + newDate)
    } catch {
      case e: Exception => e.printStackTrace()
    }
    newDate
  }

  //register for sql
  EdlSparkObjects.sparkSession.sqlContext.udf.register("convertToTimestamp", convertToTimestamp)

  // register for scala
  def convertToTimestampUDF = udf(convertToTimestamp)
  df.withColumn("LastModifiedTS", convertToTimestampUDF(col("lastModified")))

感谢您的帮助和指导。

【问题讨论】:

  • 除了不推荐使用 UDF 之外,我建议您不要使用 SimpleDateFormatTimeZone。这些类设计不良且过时,尤其是前者,尤其是出了名的麻烦。而是使用InstantZonedDateTimeDateTimeFormatter,均来自java.time, the modern Java date and time API
  • 谢谢奥莱。这里有什么使用指南吗?
  • 我只能编写 Java 代码:Instant.parse("2019-06-24T15:36:16.000Z").atZone(ZoneId.of("America/New_York")).format(DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss")) 产生 2019-06-24 11:36:16Tutorial here.

标签: scala apache-spark dataframe apache-spark-sql user-defined-functions


【解决方案1】:

您的第一次withColumn 尝试即将完成。它只包含不正确的日期格式字符串yyyy-MM-dd HH:MM:SS。此外,cast(StringType) 是不必要的,因为date_format 已经返回一个 StringType 列。以下是更正日期格式的示例代码:

import org.apache.spark.sql.functions._
import spark.implicits._

val df = Seq(
  (1, "2019-06-24T15:36:16.000Z"),
  (2, "2019-07-13T16:25:27.000Z")
).toDF("id", "lastModified")

df.withColumn("ConvertedTS", date_format(to_utc_timestamp(to_timestamp(
  $"lastModified", "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"), "America/New_York"), "yyyy-MM-dd HH:mm:ss")
).
show(false)
// +---+------------------------+-------------------+
// |id |lastModified            |ConvertedTS        |
// +---+------------------------+-------------------+
// |1  |2019-06-24T15:36:16.000Z|2019-06-24 19:36:16|
// |2  |2019-07-13T16:25:27.000Z|2019-07-13 20:25:27|
// +---+------------------------+-------------------+

【讨论】:

  • 糟糕,感谢您的指正。没看到你的回复,我才意识到。因此,如果我希望时间相同,明智的做法是使用上面相同的表达式并更改为 GMT 而不是 America/New_York 或者有其他推荐的方式。
  • @Dwarrior,要保持准确的HH:mm:ss,您可以简单地跳过to_utc_timestamp 转换以忽略时区(即date_format(to_timestamp($"lastModified", "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"), "yyyy-MM-dd HH:mm:ss"))。
  • 谢谢,这很有帮助。
猜你喜欢
  • 1970-01-01
  • 2016-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-11
  • 2020-04-03
  • 2016-11-30
  • 2020-09-28
相关资源
最近更新 更多