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

如何用Scala向PostgreSQL插入Interval类型值?报错求助

解决Scala向PostgreSQL interval字段插入数据的报错问题

问题场景

尝试用Scala计算任务运行时长,插入PostgreSQL表的interval类型字段job_run_duration时,两次尝试均出现报错:

第一次尝试代码与报错

var tm1 =  LocalDateTime.now()
var tm2 =  LocalDateTime.now()

var milliseconds = tm1.until(tm2, ChronoUnit.MILLIS)

var seconds = (milliseconds / 1000) % 60
var minutes = (milliseconds / (1000*60)) % 60
var hours   = (milliseconds / (1000*60*60)) % 24
var milisec = milliseconds - ((seconds * 1000) + (minutes * 60 * 1000) + (hours * 60 *60 * 1000))

var secondsNew = if (seconds.toString().length() == 1) "0" + seconds else seconds
var minutesNew = if (minutes.toString().length() == 1) "0" + minutes else minutes
var hoursNew = if (hours.toString().length() == 1) "0" + hours else hours
var milisecNew = if (milisec.toString().length() == 1) milisec + "00"  else if (milisec.toString().length() == 2)  milisec + "0" else milisec

var timeString = "%s:%s:%s".format(hoursNew, minutesNew, secondsNew)
var duration = LocalTime.parse(timeString)

var tm = Time.valueOf(DateTimeFormatter.ofPattern("HH:mm:ss").format(duration))

// 插入语句
sql = "INSERT into etl.mls_refresh_snapshot(job_name,job_type,job_frequency,
source_table_name,source_count,target_count,job_run_duration,started_at,ended_at) VALUES(?,?,?,?,?,?::interval,?,?)"

var statement : PreparedStatement = conn.prepareStatement(sql)
statement.setTime(6,Time.valueOf(DateTimeFormatter.ofPattern("HH:mm:ss.SSS").format(duration)))

报错信息:

java.lang.NumberFormatException: For input string: "18.000"

第二次修改后代码与报错

var timeString = "%s:%s:%s.%s".format(hoursNew, minutesNew, secondsNew, milisecNew)
var duration = LocalTime.parse(timeString)
var tm = Time.valueOf(DateTimeFormatter.ofPattern("HH:mm:ss.SSS").format(duration))

报错信息:

ERROR: invalid input syntax for type interval: "00:02:07+05:30"

问题原因

  1. 类型不匹配:Time对应SQL的TIME类型(表示一天中的时刻),并非用于传递时长的interval类型,强行将带毫秒的字符串转为Time会导致解析失败。
  2. 格式错误:LocalTime会附带时区偏移信息(如+05:30),而PostgreSQL的interval不接受带时区的格式,仅支持纯时长格式。

解决方案

方案1:直接构造PostgreSQL兼容的interval字符串

手动计算时长各部分,格式化出HH:MM:SS.SSS格式的字符串,直接通过setString传递:

val tm1 = LocalDateTime.now()
val tm2 = LocalDateTime.now()

val milliseconds = tm1.until(tm2, ChronoUnit.MILLIS)

val seconds = (milliseconds / 1000) % 60
val minutes = (milliseconds / (1000*60)) % 60
val hours   = (milliseconds / (1000*60*60)) % 24
val milisec = milliseconds % 1000 // 简化毫秒计算,直接取余1000

// 用f-string自动补零,生成标准时长格式
val intervalStr = f"$hours%02d:$minutes%02d:$seconds%02d.$milisec%03d"

// 插入SQL无需额外的::interval转换(JDBC可自动识别)
val sql = """INSERT into etl.mls_refresh_snapshot(
    job_name,job_type,job_frequency,
    source_table_name,source_count,target_count,
    job_run_duration,started_at,ended_at
) VALUES(?,?,?,?,?,?,?,?,?)"""

val statement: PreparedStatement = conn.prepareStatement(sql)
statement.setString(6, intervalStr) // 直接传递字符串格式的时长
// 设置其他参数...
statement.executeUpdate()

方案2:用Java Duration类优雅处理时长

利用Duration类直接计算时间间隔,避免手动计算错误:

val tm1 = LocalDateTime.now()
val tm2 = LocalDateTime.now()

val duration = Duration.between(tm1, tm2)

// 直接获取时长各部分
val hours = duration.toHoursPart
val minutes = duration.toMinutesPart
val seconds = duration.toSecondsPart
val millis = duration.toMillisPart

val intervalStr = f"$hours%02d:$minutes%02d:$seconds%02d.$millis%03d"

// 后续插入代码同方案1,用setString传递intervalStr

关键注意点

  • 不要用Time或LocalTime类型传递interval数据,二者分别对应时刻和带时区的时间,与时长类型不匹配。
  • PostgreSQL的interval支持多种格式,HH:MM:SS.SSS是最直观且易构造的标准格式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 18:54:53