将带有纳秒的字符串转换为spark中的时间戳

时间:2017-09-12 09:13:40

标签: datetime apache-spark apache-spark-sql

有没有办法将带有纳秒的时间戳值转换为spark中的时间戳。我从csv文件获取输入,timstamp值是格式的 12-12-2015 14:09:36.992415+01:00。这是我试过的代码。

val date_raw_data = List((1, "12-12-2015 14:09:36.992415+01:00"))

val dateraw_df = sc.parallelize(date_raw_data).toDF("ID", "TIMESTAMP_VALUE")

val ts = unix_timestamp($"TIMESTAMP_VALUE", "MM-dd-yyyy HH:mm:ss.ffffffz").cast("double").cast("timestamp")

val date_df = dateraw_df.withColumn("TIMESTAMP_CONV", ts).show(false)

输出

+---+-----------------------+---------------------+
|ID |TIMESTAMP_VALUE        |TIMESTAMP_CONV       |
+---+-----------------------+---------------------+
|1  |12-12-2015 14:09:36.992|null                 |
+---+-----------------------+---------------------+

我能够使用格式MM-dd-yyyy HH:mm:ss.SSS转换毫秒级的时间戳。麻烦在于纳秒级和时区格式。

2 个答案:

答案 0 :(得分:2)

unix_timestamp不会在这里做。即使您可以解析字符串(AFAIK SimpleDateFormat不提供所需的格式),unix_timestamp has only second precision(强调我的):

  

def unix_timestamp(s: Column, p: String): Column

     

将具有给定模式的时间字符串(请参阅[http://docs.oracle.com/javase/tutorial/i18n/format/simpleDateFormat.html])转换为Unix时间戳(以秒为单位),如果失败则返回null。

您必须创建自己的函数来解析此数据。一个粗略的想法:

import org.apache.spark.sql.functions._
import org.apache.spark.sql.Column

def to_nano(c: Column) = {
  val r = "([0-9]{2}-[0-9]{2}-[0-9]{4} [0-9]{2}:[0-9]{2}:[0-9]{2})(\\.[0-9]*)(.*)$"
  // seconds part
  (unix_timestamp(
    concat(
      regexp_extract($"TIMESTAMP_VALUE", r, 1),
      regexp_extract($"TIMESTAMP_VALUE", r, 3)
    ), "MM-dd-YYYY HH:mm:ssXXX"
  ).cast("decimal(38, 9)") + 
  // subsecond part
  regexp_extract($"TIMESTAMP_VALUE", r, 2).cast("decimal(38, 9)")).alias("value")
}

Seq("12-12-2015 14:09:36.992415+01:00").toDF("TIMESTAMP_VALUE")
  .select(to_nano($"TIMESTAMP_COLUMN").cast("timestamp"))
  .show(false)

// +--------------------------+
// |value                     |
// +--------------------------+
// |2014-12-28 14:09:36.992415|
// +--------------------------+

答案 1 :(得分:0)

如果您不关心纳秒级的问题,那么这里会有一个没有UDF的肮脏dirty俩。 (我不能在需要的地方使用UDF,也不能修改源代码)

select CAST(UNIX_TIMESTAMP(substr(date,0,length(date)-4), "yyyy-MM-dd'T'HH:mm:ss.SSS") AS TIMESTAMP);

例如

select CAST(UNIX_TIMESTAMP(substr("2020-09-14T01:14:15.596444Z",0,length("2020-09-14T01:14:15.596444Z")-4), "yyyy-MM-dd'T'HH:mm:ss.SSS") AS TIMESTAMP);

我基本上是将字符串从纳秒部分中剥离出来,然后使用与Spark SimpleDateFormat兼容的解析器来解析其余部分。

请未来的雇主,不要以这个答复来评判我。