You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scala Spark中case class的Date列格式如何转换?

Scala Spark 不同日期格式CSV合并解决方案

核心问题说明

java.sql.Date.valueOf()方法仅支持解析yyyy-MM-dd格式的字符串,第二个文件的dd-MM-yyyy格式字符串不符合要求,所以触发格式错误。你只需要自定义日期解析逻辑,将第二个文件的日期统一转为和第一个文件相同的java.sql.Date类型,即可正常合并。


方法1:适配RDD + case class场景

步骤1:导入依赖并定义公共解析逻辑

使用Java 8+ 原生java.time包下的线程安全日期工具,避免分布式场景下的解析异常:

import java.time.LocalDate
import java.time.format.DateTimeFormatter
import java.sql.Date
import org.apache.spark.rdd.RDD

// 你的业务case class,其他字段按实际结构补充即可
case class DailyData(date: Date, col1: String, col2: Int /* 剩余7个字段自行补充 */)

// 全局复用dd-MM-yyyy格式解析器
private val ddMmYyyyFormatter: DateTimeFormatter = DateTimeFormatter.ofPattern("dd-MM-yyyy")
def parseDdMmYyyyToSqlDate(dateStr: String): Date = {
  val localDate = LocalDate.parse(dateStr, ddMmYyyyFormatter)
  Date.valueOf(localDate) // 输出格式和第一个文件的Date类型完全一致
}

步骤2:处理第二个文件的RDD映射

将原来调用Date.valueOf()的位置替换为自定义解析方法即可:

// 读取第二个CSV文件
val secondRawRdd: RDD[String] = spark.sparkContext.textFile("你的第二个CSV文件路径")
val secondSchemaRdd: RDD[DailyData] = secondRawRdd
  .map(line => line.split(",")) // 若CSV分隔符不是逗号请自行替换
  .map(arr => {
    // 假设Date为第0列,按照你实际的字段顺序修改索引和类型转换逻辑
    val parsedDate = parseDdMmYyyyToSqlDate(arr(0))
    DailyData(parsedDate, arr(1), arr(2).toInt /* 剩余字段按实际映射 */)
  })

步骤3:合并两个RDD

两个RDD的schema完全一致,直接调用union合并:

// 假设第一个文件处理后的RDD为firstSchemaRdd
val mergedRdd: RDD[DailyData] = firstSchemaRdd.union(secondSchemaRdd)

方法2:更推荐的DataFrame API方案

如果不强制要求手动构造RDD,用Spark原生CSV读取参数指定日期格式更简洁,无需自定义解析逻辑:

import org.apache.spark.sql.types.StructType
// 提前定义统一的表schema,也可以用case class自动生成Encoders
val commonSchema: StructType = ??? // 你的10列表结构定义

// 读取第一个文件
val firstDf = spark.read
  .option("header", "true") // 若CSV有表头开启,无则关闭
  .option("dateFormat", "yyyy-MM-dd")
  .schema(commonSchema)
  .csv("第一个文件路径")

// 读取第二个文件,仅修改日期格式参数即可
val secondDf = spark.read
  .option("header", "true")
  .option("dateFormat", "dd-MM-yyyy")
  .schema(commonSchema)
  .csv("第二个文件路径")

// 合并DataFrame,如需转回RDD调用.as[DailyData].rdd即可
val mergedDf = firstDf.unionByName(secondDf)

注意事项

  • 禁止使用java.text.SimpleDateFormat做日期解析,该类线程不安全,分布式运行时会出现偶发解析错误
  • RDD合并前需要确认两个RDD的case class字段顺序、字段类型完全一致,否则会触发运行时报错
  • 若CSV带表头,读取RDD时需要先跳过首行,避免表头行解析失败

内容的提问来源于stack exchange,提问作者Priyad Harsh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.11 15:36:01