首页 > 解决方案 > 在 Scala 中仅过滤特定格式的日期

问题描述

我有一个数据框,其中一些字段的日期格式为 D.HH:mm:ss、D.HH:mm:ss.SSSSSSS & HH:mm:ss.SSSSSSS。我只需要过滤 HH:mm:ss.SSSSSSS 类型的日期,然后将此日期转换为秒(整数)。

我在下面编写了将日期转换为秒的 scala 代码。我需要帮助来过滤特定格式的日期类型(HH:mm:ss.SSSSSSS)并跳过数据框中的其他日期格式。任何帮助,将不胜感激。

 def hoursToSeconds(a: Any): Int = {
  val sec = a.toString.split('.')
  val fields = sec(0).split(':')
  val creationSeconds = fields(0).toInt*3600 + fields(1).toInt*60 + fields(2).toInt
  return creationSeconds
}

标签: scalaapache-sparkuser-defined-functions

解决方案


任务可以分为两部分:

  1. 在rlike的帮助下过滤所需的行
  2. 计算 udf 中的秒数

创建一些测试数据:

val df = Seq(
   ("one", "1.09:39:26"),
   ("two", "1.09:39:26.1234567"),
   ("three", "09:39:26.1234567")
 ).toDF("info", "time")

regexp和udf的定义:

val pattern = "\\A(\\d{1,2}):(\\d{2}):(\\d{2})\\.\\d{7}\\z".r

val toSeconds = udf{in: String => {
  val pattern(hour, minute, second) = in
  hour.toInt * 60 * 60 + minute.toInt * 60 + second.toInt
}}

实际代码:

df
  .filter('time rlike pattern.regex)
  .select('info, 'time, toSeconds('time).as("seconds"))
  .show

印刷

+-----+----------------+-------+
| info|            time|seconds|
+-----+----------------+-------+
|three|09:39:26.1234567|  34766|
+-----+----------------+-------+

如果应该保留不具有正确格式的行,可以稍微更改 udf 并且必须删除过滤器:

val pattern = "\\A(\\d{1,2}):(\\d{2}):(\\d{2})\\.\\d{7}\\z".r

val toSeconds = udf{in: String => {
  in match {
    case pattern(hour, minute, second)=> hour.toInt * 60 * 60 + minute.toInt * 60 + second.toInt
    case _ => 0
  }
}}

df
  .select('info, 'time, toSeconds('time).as("seconds"))
  .show

印刷

+-----+------------------+-------+
| info|              time|seconds|
+-----+------------------+-------+
|  one|        1.09:39:26|      0|
|  two|1.09:39:26.1234567|      0|
|three|  09:39:26.1234567|  34766|
+-----+------------------+-------+

推荐阅读