spark scala long преобразуется во временную метку с миллисекундами в паркетном фрейме данных

#scala #date #apache-spark #unix-timestamp

#scala #Дата #apache-spark #unix-временная метка

Вопрос:

Не мог бы кто-нибудь подсказать мне, как преобразовать long в временную метку с миллисекундами? Я знаю, как это сделать yyyy-MM-dd HH:mm:ss , но я бы хотел, чтобы миллисекунды yyyy-MM-dd HH:mm:ss.SSS

Моя структура parquet выглядит следующим образом

 |-- header: struct (nullable = true)
 |    |-- time: long (nullable = true)
...
  

Один образец для времени равен 1600676073054:

Scala

 scala> spark.sql("select from_unixtime(word) as ts, word from tmp_1").show(false)
 -------------------- ------------- 
|ts                  |word         |
 -------------------- ------------- 
|52693-05-28 18:30:54|1600676073054|
 -------------------- ------------- 


scala> spark.sql("select from_unixtime(word/1000) as ts, word from tmp_1").show(false)
 ------------------- ------------- 
|ts                 |word         |
 ------------------- ------------- 
|2020-09-21 16:14:33|1600676073054|
 ------------------- ------------- 


scala> spark.sql("select from_unixtime(word) as ts, word from tmp_1").show(false)
 -------------------- ------------- 
|ts                  |word         |
 -------------------- ------------- 
|52693-05-28 18:30:54|1600676073054|
 -------------------- ------------- 

  

Sql Server

 declare @StartDate datetime2(3) = '1970-01-01 00:00:00.000'
, @milliseconds bigint = 1600676073054
, @MillisecondsPerDay int = 60 * 60 * 24 * 1000 -- = 86400000

SELECT  DATEADD(MILLISECOND, TRY_CAST(@milliseconds % @millisecondsPerDay AS INT), DATEADD(DAY, TRY_CAST(@milliseconds / @millisecondsPerDay AS INT), @StartDate));
--2020-09-21 08:14:33.054
  

Я хотел бы знать, как преобразовать 054 в миллисекунды.

Спасибо.

Комментарии:

1. вывод scala в моем местном часовом поясе: 2020-09-21 16:14:33. вывод sqlserver в часовом поясе PST 2020-09-21 08:14:33.054, мы можем игнорировать разные часы, спасибо.

Ответ №1:

Spark не поддерживает миллисекунды эпохи, поэтому вам нужно разделить его на 1000.

 val df = spark.createDataFrame(
    Seq(
        
       (1, "1600676073054")
    )
).toDF("id","long_timestamp")


 df.withColumn(
        "timestamp_mili",
        (col("long_timestamp")/1000).cast("timestamp") 
    ).show(false)
    
  // --- -------------- ----------------------- 
  //|id |long_timestamp|timestamp_mili         |
  // --- -------------- ----------------------- 
  //|1  |1600676073054 |2020-09-21 08:14:33.054|
  // --- -------------- -----------------------