如何将java.time.Duration转换为java.sql.Time?

时间:2016-06-25 21:28:38

标签: java sql jdbc time

java.time.Duration - 对象转换为java.sql.Time的最佳方式是什么?

我得到的是像PT15M51S这样的ISO8601字符串,Duration.parse(String s)非常适合这种情况。

但现在我正在努力如何使用java.sql.TimePreparedStatement转换为setTime(java.sql.Time time),并使用JDBC将其存储在我的MySQL数据库中。

我最后写了一封来自org.apache.commons.lang3.time.DurationFormatUtils的绦虫:

java.sql.Time.valueOf(DurationFormatUtils.formatDurationHMS(video.getDuration().toMillis())))

对于下一个问题:如何从java.time.Duration获取java.sql.Time

2 个答案:

答案 0 :(得分:4)

java.sql.Time 持续时间,是一天内的时间(即正常的24小时制)。在其中存储持续时间是一种黑客攻击,如果持续时间超过24小时,黑客将会中断。最好将其存储为ISO持续时间字符串,或者以数字数据类型(例如,双精度或数字)存储,或者如果数据库支持它:在interval中。

但是,如果您仍希望将持续时间存储在sql TIME中:使用java.sql.Time.valueOf(LocalTime)java.timejava.sql.Time的转换点为java.time.LocalTime。因此,要从Duration转换为java.sql.Time,您可以执行以下操作:

Duration duration = ..;
LocalTime localTime = LocalTime.MIDNIGHT.plus(duration);
java.sql.Time sqlTime = java.sql.Time.valueOf(localTime);

转换回来是:

java.sql.Time sqlTime = ..;
LocalTime localTime = sqlTime.toLocalTime();
Duration duration = Duration.between(LocalTime.MIDNIGHT, localTime);

请注意,java.sql.Time可能只有几秒钟的精度。使用符合JDBC 4.2的驱动程序时,不需要转换为java.sql.Time,因为使用java.time.LocalTimesetObject(1, <your LocalTime>)直接支持存储getObject(1, java.time.LocalTime.class)

答案 1 :(得分:1)

数据库结构是否已修复?我认为TIMETIMESTAMP可能不是持续时间最佳的数据类型。我会将列类型更改为BIGINT(又名Long),并使用Duration.toMillis()将持续时间转换为毫秒(或纳秒,具体取决于您的需要)。

如果这不是一个选项,您可以使用类似的逻辑,并将持续时间表示为某个时间戳的偏移量,例如1970-01-01T00:00:00.000Z Duration.addTo(referenceDate)java.sql.Time(durationInMillis)。要再次获取Duration的实例,您需要使用Duration.ofMillis(sqlTime.getTime())

这些基本上是您的选择:

使用BIGINT作为列类型(首选解决方案):

// from java.time.Duration to java.lang.Long
{
    final Duration duration = ...
    final PreparedStatement pStmnt = con.prepareStatement("...");
    pStmnt.setLong(n, duration.toMillis());
}

// from java.lang.Long to java.time.Duration
{
    final PreparedStatement pStmnt = con.prepareStatement("...");
    final ResultSet resultSet = pStmnt.getResultSet();
    while (resultSet.next()) {
        final Long durationInMillis = resultSet.getLong(n);
        final Duration duration = Duration.ofMillis(durationInMillis);
        ...
    }
}

使用TIMETIMESTAMP作为列类型。您可以使用以下代码中的java.sql.Time替换java.sql.Timestamp,具体取决于您的实际列类型:

// from java.time.Duration to java.sql.Time(stamp)
{
    final Duration duration = ...
    final Time time = new Time(duration.toMillis());

    final PreparedStatement pStmnt = con.prepareStatement("...");
    pStmnt.setTime(n, time);
}

// from java.sql.Time(stamp) to java.time.Duration
{
    final PreparedStatement pStmnt = con.prepareStatement("...");
    final ResultSet resultSet = pStmnt.getResultSet();
    while (resultSet.next()) {
        final Time time = resultSet.getTime(n);
        final Duration duration = Duration.ofMillis(time.getTime());
        ...
    }
}

根据MySQL的文档,TIME类型支持从-838:59:59838:59:59的范围(请参阅here)。但默认情况下,除非在数据库列的创建时指定了所需的精度,否则TIMEDATETIMESTAMP类型都不支持小数秒(请参阅here)。那就是在TIME列中存储毫秒,需要像这样创建表:

CREATE TABLE t1 (t TIME(3));

<强>更新

  • 添加了更详细的代码示例
  • 添加了有关TIME
  • 支持的最小值最大值的MySQL文档链接