将火花数据帧中的日期时间时间戳转换为 epocTimestamp

Posted

技术标签:

【中文标题】将火花数据帧中的日期时间时间戳转换为 epocTimestamp【英文标题】:Convert date time timestamp in spark dataframe to epocTimestamp 【发布时间】:2020-12-04 15:16:39 【问题描述】:

我有一个带有时间戳列的镶木地板文件,格式为2020-07-07 18:30:14.500000+00:00,由 pandas 编写。当我在 spark 中读取同一个 parquet 文件时,它被读取为2020-07-08 00:00:14.5

我想将其转换为以毫秒为单位的纪元时间戳,即 1594146614500

我尝试过使用 java 日期时间格式

val dtformat = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS")
dtformat.parse(r2.getAs[Long]("date_time").toString).getTime

它正在转换但错误的值 (1594146614005) 而不是 1594146614500。

为了使它正确,我必须添加 dtformat.parse(r2.getAs[Long]("date_time").toString+"00").getTime 。 还有比这更干净的方法吗?

spark 中的任何可用函数以毫秒为单位读取它?

更新 1:

使用以下答案后:

df.withColumn("timestamp", to_timestamp($"date_time", "yyyy-MM-dd HH:mm:ss.SSSSSSXXX")).withColumn("epoch", ($"timestamp".cast("十进制(20, 10)") * 1000).cast("bigint")).show()

+-------------+--------------------+-------------------+-------------+
|expected_time|       original_time|          timestamp|        epoch|
+-------------+--------------------+-------------------+-------------+
|1597763904500|2020-08-18 20:48:...|2020-08-18 20:48:24|1597763904000|
|1597763905000| 2020-08-18 20:48:25|2020-08-18 20:48:25|1597763905000|
|1597763905500|2020-08-18 20:48:...|2020-08-18 20:48:25|1597763905000|

缺点是假设如果数据的粒度为 500ms,那么每个时间戳都有两个相同的 epoc 时间戳,这是不期望的。

【问题讨论】:

我建议你不要使用SimpleDateFormat。这个类是出了名的麻烦和过时。而是使用来自java.time, the modern Java date and time API 的LocalDateTimeDateTimeFormatterSimpleDateFormat 也无法解析 2020-07-08 00:00:14.5。它只支持毫秒,精确到秒的三位小数。 【参考方案1】:

我建议您从 java.util 和相应的格式化 API (java.text.SimpleDateFormat) 切换到过时的容易出错的日期/时间 API 到 java.time 的 modern date/time API 和相应的格式化 API (java.time.format )。从 Trail: Date Time

了解有关现代日期时间 API 的更多信息
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;

public class Main 
    public static void main(String[] args) 
        OffsetDateTime odt = OffsetDateTime.parse("2020-07-07 18:30:14.500000+00:00",
                DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSSSSSZZZZZ"));
        System.out.println(odt.toInstant().toEpochMilli());
    

输出:

1594146614500

【讨论】:

【参考方案2】:

使用 spark 数据框功能,

df.withColumn("timestamp", to_timestamp($"time", "yyyy-MM-dd HH:mm:ss.SSSSSSXXX"))
  .withColumn("epoch", ($"timestamp".cast("decimal(20, 10)") * 1000).cast("bigint"))
  .show(false)

+--------------------------------+---------------------+-------------+
|time                            |timestamp            |epoch        |
+--------------------------------+---------------------+-------------+
|2020-07-07 18:30:14.500000+00:00|2020-07-07 18:30:14.5|1594146614500|
+--------------------------------+---------------------+-------------+

这也是一种可行的方法。

【讨论】:

感谢@Lamanus,使用它有一个缺点,如果数据的粒度为 500 毫秒,那么每个时间戳都有两个与我在问题中更新的值相同的值。 我不明白。您的原始时间没有正确显示,甚至格式看起来也不同。

以上是关于将火花数据帧中的日期时间时间戳转换为 epocTimestamp的主要内容,如果未能解决你的问题,请参考以下文章

将字符串格式的科学记数法转换为火花数据帧中的数字[重复]

遍历 Float 时间戳的 Pandas DataFrame 并转换为日期时间

将 JSON 时间戳字符串转换为 pandas 数据框中的 python 日期

如何将所有日期格式转换为日期列的时间戳?

将数据推送到数组中,但在将时间戳转换为日期之后

如何在雪花中将时间戳转换为日期