在 spark DataFrame-Scala 中格式化 TimestampType

Posted

技术标签:

【中文标题】在 spark DataFrame-Scala 中格式化 TimestampType【英文标题】:Format TimestampType in spark DataFrame- Scala 【发布时间】:2017-07-06 18:21:54 【问题描述】:

当我尝试将字符串字段转换为 Spark DataFrame 中的 TimestampType 时,输出值以微秒精度(yyyy-MM-dd HH:mm:ss.S)出现。但我需要格式为yyyy-MM-dd HH:mm:ss,即不包括微秒精度。另外,我想在写入镶木地板文件时将其保存为时间戳字段。 所以我的字段的数据类型应该是yyyy-MM-dd HH:mm:ss格式的时间戳

我尝试使用 TimestampType 作为

col("column_A").cast(TimestampType)
or
col("column_A").cast("timestamp")

将字段转换为时间戳。它们能够将字段转换为时间戳,但精度为微秒。

任何人都可以帮助将时间戳数据类型保存到具有所需格式规范的镶木地板文件中。 编辑 输入:

val a = sc.parallelize(List(("a", "2017-01-01 12:02:00.0"), ("b", "2017-02-01 11:22:30"))).toDF("cola", "colb")
scala> a.withColumn("datetime", date_format(col("colb"), "yyyy-MM-dd HH:mm:ss")).show(false)
+----+---------------------+-------------------+
|cola|colb                 |datetime           |
+----+---------------------+-------------------+
|a   |2017-01-01 12:02:00.0|2017-01-01 12:02:00|
|b   |2017-02-01 11:22:30  |2017-02-01 11:22:30|
+----+---------------------+-------------------+


scala> a.withColumn("datetime", date_format(col("colb"), "yyyy-MM-dd HH:mm:ss")).printSchema
root
 |-- cola: string (nullable = true)
 |-- colb: string (nullable = true)
 |-- datetime: string (nullable = true)

在上面,我们得到了正确的时间戳格式,但是当我们打印 Schema 时,datetime 字段的类型是 String,但我这里需要一个时间戳类型。

现在,如果我尝试将该字段转换为时间戳,则格式设置为微秒精度,这不是预期的。

scala> import org.apache.spark.sql.types._
import org.apache.spark.sql.types._

scala> val a = sc.parallelize(List(("a", "2017-01-01 12:02:00.0"), ("b", "2017-02-01 11:22:30"))).toDF("cola", "colb")
a: org.apache.spark.sql.DataFrame = [cola: string, colb: string]

scala> a.withColumn("datetime", date_format(col("colb").cast(TimestampType), "yyyy-MM-dd HH:mm:ss").cast(TimestampType)).show(false)
+----+---------------------+---------------------+
|cola|colb                 |datetime             |
+----+---------------------+---------------------+
|a   |2017-01-01 12:02:00.0|2017-01-01 12:02:00.0|
|b   |2017-02-01 11:22:30  |2017-02-01 11:22:30.0|
+----+---------------------+---------------------+


scala> a.withColumn("datetime", date_format(col("colb").cast(TimestampType), "yyyy-MM-dd HH:mm:ss").cast(TimestampType)).printSchema
root
 |-- cola: string (nullable = true)
 |-- colb: string (nullable = true)
 |-- datetime: timestamp (nullable = true)

我期望格式为yyyy-MM-dd HH:mm:ss,字段的数据类型为timestamp 提前致谢

【问题讨论】:

【参考方案1】:

我认为您缺少的是时间戳/日期时间字段在本机存储中没有可读格式。格式是浮点数、INT96 或其他格式,具体取决于数据库。格式化日期时间/时间戳以提高可读性一直是一个报告问题(即,由准备显示数据的工具执行),这就是为什么您注意到当您为日期提供字符串格式时,它正确地将其转换为存储作为一个字符串。数据库 (spark) 只存储确切知道时间值是什么所需的内容。

您可以指定时间戳值不包含毫秒,即毫秒值 0,但不能指定它不应该显示毫秒。

这类似于在数字列上指定舍入行为(也是报告问题)。

【讨论】:

【参考方案2】:

您可以使用unix_timestamp 将字符串日期时间转换为时间戳。

unix_timestamp(Column s, String p) 用给定的时间字符串转换 模式(见 [http://docs.oracle.com/javase/tutorial/i18n/format/simpleDateFormat.html]) 到 Unix 时间戳(以秒为单位),如果失败则返回 null。

val format = "yyyy-MM-dd HH:mm:ss"
dataframe.withColumn("column_A", unix_timestamp($"date", format))

希望这会有所帮助!

【讨论】:

以上是关于在 spark DataFrame-Scala 中格式化 TimestampType的主要内容,如果未能解决你的问题,请参考以下文章

如何在 spark-shell (spark 2.1.1) 中启用对 spark 的 Hive 支持

在 EMR 集群中运行 Spark 应用程序时在哪里指定 Spark 配置

如何在单个 Spark 作业中摄取不同的 Spark 数据帧

在 Spark 上下文中使用多个同时作业的 Spark 2 作业监控 (JobProgressListener)

如何在 Zeppelin 中切换 Spark 版本以使用 Spark 3.x

在 Spark 中使用 map() 和 filter() 而不是 spark.sql