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
相关产品推荐
相关产品推荐

