【问题标题】:How to convert ISO 8601 duration to seconds如何将 ISO 8601 持续时间转换为秒
【发布时间】:2020-08-11 15:56:08
【问题描述】:

我在 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

如果我以这种方式成功,那么将不得不在整个数据框列上应用额外的逻辑

【问题讨论】:

    标签: java scala apache-spark


    【解决方案1】:

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

    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|
    +---------------+-------+
    */
    
    

    【讨论】:

    • 您的解决方案只考虑T 之后的部分。当涉及到一天时,我如何处理这个案子例如:P0Y0M2DT23H59M56S 根据上面的代码 ir 出来为86396 但它应该是259196 sathya @ sathya
    • @PriyalChaudhari:让我今天晚些时候检查一下
    • 谢谢!我也在尝试,但无法解析我上面给出的值。关注此文档docs.oracle.com/javase/8/docs/api/java/time/Duration.html
    • 我不认为 java.time.Duration.parse 可以处理 P0Y0M2DT23H59M56S 格式的字符串。我找到了这个github.com/MenoData/Time4J,但不知道如何使用它
    【解决方案2】:

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

    我们需要使用 time4j 库: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|
    +-----------------+-------+
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-07-04
      • 1970-01-01
      • 2013-10-05
      • 1970-01-01
      • 2013-10-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多