在spark DataFrame中格式化TimestampType - Scala

3
在Spark DataFrame中,当我试图将一个字符串字段转换为TimestampType时,输出值带有微秒精度(yyyy-MM-dd HH:mm:ss.S)。但我需要的格式是yyyy-MM-dd HH:mm:ss,即不包括微秒精度。此外,我希望在写入Parquet文件时将其保存为时间戳字段,因此我的字段数据类型应该是格式为yyyy-MM-dd HH:mm:ss的时间戳。
我尝试使用TimestampType作为:
col("column_A").cast(TimestampType)
or
col("column_A").cast("timestamp")

将字段转换为时间戳。这些能够将字段转换为带有微秒精度的时间戳。

有人能帮忙将时间戳数据类型保存到具有所需格式规范的parquet文件中吗?
编辑
输入:

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字段的类型是字符串,而我需要在此处使用时间戳类型。
现在,如果我尝试将该字段转换为时间戳,格式将被设置为微秒精度,这并不是想要的结果。
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。谢谢。
2个回答

2
我认为你忽略了时间戳/日期时间字段在本地存储中没有可读格式。格式是浮点数、INT96或者根据数据库而异。将日期时间字段格式化以便阅读一直都是报告的问题(即由准备数据显示的工具执行),这就是为什么当你提供一个字符串格式的日期时,它会被正确地转换为字符串进行存储。数据库(Spark)只存储确切需要知道时间值的内容。
你可以指定时间戳值没有毫秒,即毫秒值为0,但不能指定不显示毫秒。
这类似于指定数字列的舍入行为(也是报告问题)。

1
你可以使用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))

希望这有所帮助!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接