【问题标题】:Convert date time timestamp in spark dataframe to epocTimestamp将火花数据帧中的日期时间时间戳转换为 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 APILocalDateTimeDateTimeFormatterSimpleDateFormat 也无法解析 2020-07-08 00:00:14.5。它只支持毫秒,精确到秒的三位小数。

标签: apache-spark datetime apache-spark-sql java-time instant


【解决方案1】:

我建议您从 java.util 和相应的格式化 API (java.text.SimpleDateFormat) 切换到过时的容易出错的日期/时间 API 到 java.timemodern 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 毫秒,那么每个时间戳都有两个与我在问题中更新的值相同的值。
    • 我不明白。您的原始时间没有正确显示,甚至格式看起来也不同。
    猜你喜欢
    • 2021-12-19
    • 1970-01-01
    • 2021-07-02
    • 1970-01-01
    • 1970-01-01
    • 2019-10-30
    • 1970-01-01
    • 2017-04-25
    • 2022-01-08
    相关资源
    最近更新 更多