有没有办法将带有纳秒的时间戳值转换为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
转换毫秒级的时间戳。麻烦在于纳秒级和时区格式。
答案 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兼容的解析器来解析其余部分。
请未来的雇主,不要以这个答复来评判我。