Spark Scala - 使用 rlike 将 DataFrame 列转换为时间类型时出错

问题描述 投票:0回答:1

我在尝试转换存储在 Spark DataFrame 中的原始时间字符串 (hh:mm:ss) 时遇到问题,其中我使用列类型为“string”的 StructType。目标是将这些时间值写入关系数据库,其中目标列类型为“时间”。

val timeRegex = "(([0-1]?[0-9])|(2[0-3])):[0-5][0-9]:[0-5][0-9]"
        var convertedData = newData

    newData.schema.fields.foreach { field =>
      val columnName = field.name
      val dataType = field.dataType

      if (dataType == StringType) {
        convertedData = convertedData.withColumn(
          columnName,
          when(expr(s"col($columnName) rlike '$timeRegex'"),
            to_utc_timestamp(substring(col(columnName), 1, 8), "HH:mm:ss").cast("timestamp").cast("time"))
            .otherwise(col(columnName))
        )
      }
    }

newData 是包含我的数据的数据框,时间列是 hh:mm:ss 格式的字符串。 但是,当任何字符串(甚至是“ABCDF_12345”等非时间字符串)与 timeRegex 匹配时,就会出现问题。这会导致 else 块尝试转换为时间戳,从而导致错误。

我正在寻求有关如何修改代码或改进正则表达式的建议,以确保仅转换有效的时间字符串,而其他字符串保持不变。当前的正则表达式似乎过于宽松,允许非时间字符串匹配。

任何在 Spark SQL 中实现此转换的见解或替代方法将不胜感激。

regex dataframe scala apache-spark time
1个回答
0
投票

如果 Postgres Time 列可以接受 Spark Timestamp,则带有时间的 String 字段可以转换为 Timestamp;无效时间将被转换为空值:

val df = Seq("ABCDF_12345", "13:04:22").toDF
val timeRegex = "(([0-1]?[0-9])|(2[0-3])):[0-5][0-9]:[0-5][0-9]"

val stringFieldNames = df.schema.fields
  .filter(_.dataType == StringType)
  .map(_.name)

def castToTimestamp = (fieldName: String) => when(expr(s"$fieldName rlike '$timeRegex'"), col(fieldName).cast(TimestampType))
val result = stringFieldNames.foldLeft(df)((acc, fieldName) => acc.withColumn(fieldName, castToTimestamp(fieldName)))

结果:

+-------------------+
|value              |
+-------------------+
|null               |
|2023-12-04 13:04:22|
+-------------------+

结果架构:

root
 |-- value: timestamp (nullable = true)
© www.soinside.com 2019 - 2024. All rights reserved.