如何将ISO 8601持续时间转换为秒

问题描述

我在spark数据框中有一个列 时间跨度 值在iso 8601持续时间内 例如:P0Y0M0DT0H5M35S 。我想将这些值转换为秒。 spark或Scala中是否有功能可以帮助我做到这一点?我正在寻找一种方法,但未成功 我尝试了持续时间

import java.time.Duration
java.time.Duration.parse("P0Y0M0DT0H5M35S")

这给我带来了错误

java.time.format.DateTimeParseException: Text cannot be parsed to a Duration

在将值传递给函数时,我做错了什么吗?我找到了这份文件 https://docs.oracle.com/javase/8/docs/api/java/time/Duration.html

如果我以这种方式成功完成操作,则必须在整个dataframe列上应用其他逻辑

解决方法

希望以下方法对您有所帮助。

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

val isoToSecondsUDF = udf( (value: String) => (java.time.Duration.parse("PT".concat(value.split("T")(1))).get(java.time.temporal.ChronoUnit.SECONDS)))

val df=Seq(("P0Y0M0DT0H5M35S")).toDF("value")

df.withColumn("seconds",isoToSecondsUDF($"value")).show()
/*
+---------------+-------+
|          value|seconds|
+---------------+-------+
|P0Y0M0DT0H5M35S|    335|
+---------------+-------+
*/

,

更新了解决方案以涵盖存在月份和日期的情况 例如:P0Y0M2DT23H59M56S。和P0Y1M2DT23H59M56S

我们将需要使用time4j lib:https://github.com/MenoData/Time4J

这是代码:

import org.apache.spark.sql.types._
import org.apache.spark.sql.functions._
import  net.time4j.Duration


def getSeconds(value: String) : String={
var b = Duration.parsePeriod(value).toTemporalAmount().get(java.time.temporal.ChronoUnit.MONTHS)
var c = Duration.parsePeriod(value).toTemporalAmount().get(java.time.temporal.ChronoUnit.DAYS)
var days =((b*30)+c).toString()
var seconds = (java.time.Duration.parse("P".concat(days).concat("DT").concat(if(value.contains("T")) value.split("T")(1) else value.split("D")(1))).get(java.time.temporal.ChronoUnit.SECONDS)).toString()
return seconds
}
val isoToSecondsUDF = udf( (value: String) => getSeconds(value))
spark.udf.register("isoToSecondsUDF",isoToSecondsUDF)
val df=Seq(("P0Y0M2DT23H59M56S")).toDF("value")
df.withColumn("seconds",isoToSecondsUDF($"value")).show()

首先获取月份数,然后转换为天数并将其添加到现有的天数中,然后将其传递给解析方法。 @sathya

输出:

+-----------------+-------+
|            value|seconds|
+-----------------+-------+
|P0Y0M2DT23H59M56S| 259196|
+-----------------+-------+

+-----------------+-------+
|            value|seconds|
+-----------------+-------+
|P0Y1M2DT23H59M56S|2851196|
+-----------------+-------+