简体   繁体   English

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

[英]How to convert java.time.Duration to java.sql.Time?

What is the best way to convert a java.time.Duration -object to java.sql.Time ? java.time.Duration转换为java.sql.Time的最佳方法是什么?

I am getting an ISO8601-String like PT15M51S and Duration.parse(String s) is quite suitable in this case. 我正在获得像PT15M51S这样的ISO8601-String,并且Duration.parse(String s)非常适合这种情况。

But now I'm struggling how to get the java.sql.Time to but it into PreparedStatement with setTime(java.sql.Time time) to store it in my MySQL-database using JDBC. 但现在我挣扎如何获得java.sql.Time到,但它进入PreparedStatementsetTime(java.sql.Time time)使用JDBC来将其存储在我的MySQL数据库。

I ended up writing a tapeworm like from org.apache.commons.lang3.time.DurationFormatUtils : 我最终从org.apache.commons.lang3.time.DurationFormatUtils编写了一个Tapeworm:

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

And for the next problem: How to get java.time.Duration from a java.sql.Time . 对于下一个问题:如何从java.sql.Time获取java.time.Duration

A java.sql.Time is not a duration, it is a time within a day (ie the normal 24 hour clock). java.sql.Time 不是持续时间,而是一天中的时间(即正常的24小时制)。 Storing a duration in it is a hack and that hack will break if that duration is longer than 24 hours. 在其中存储持续时间是一个hack,如果该持续时间超过24小时,该hack将中断。 You are better off storing it as the ISO duration string, or in a number datatype (eg double, or maybe numeric) or if your database supports it: in an interval . 最好将其存储为ISO持续时间字符串,数字数据类型(例如,双精度或数字)或数据库支持的interval

However if you still want to store the duration in a sql TIME : The conversion point from java.time to java.sql.Time is java.time.LocalTime using java.sql.Time.valueOf(LocalTime) . 但是,如果您仍想将持续时间存储在sql TIME :使用java.sql.Time.valueOf(LocalTime) java.time.LocalTime java.sql.Time.valueOf(LocalTime)java.timejava.sql.Time的转换点是java.time.LocalTime So to convert from a Duration to java.sql.Time you can do: 因此,要从Duration转换为java.sql.Time您可以执行以下操作:

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

The conversion back would be: 转换回将是:

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

Be aware that a java.sql.Time might only have precision in seconds. 请注意, java.sql.Time可能只具有几秒钟的精度。 With a JDBC 4.2 compliant driver conversion to java.sql.Time is not necessary because storing a java.time.LocalTime is supported directly using setObject(1, <your LocalTime>) and getObject(1, java.time.LocalTime.class) . 用JDBC 4.2兼容的驱动程序转换到java.sql.Time是没有必要的,因为存储java.time.LocalTime使用直接支撑setObject(1, <your LocalTime>)getObject(1, java.time.LocalTime.class)

Is the database structure fixed? 数据库结构是否固定? I think TIME or TIMESTAMP is probably not the best data type for duration. 我认为TIMETIMESTAMP可能不是持续时间的最佳数据类型。 I would change the column type to BIGINT (aka Long ) and convert the duration to milliseconds (or nanoseconds depending on your needs) with Duration.toMillis() . 我将列类型更改为BIGINT (aka Long ),并使用Duration.toMillis()将持续时间转换为毫秒(或纳秒,具体取决于您的需求Duration.toMillis()

If this is not an option, you could use a similar logic and represent the duration as offset from a certain timestamp, such as 1970-01-01T00:00:00.000Z with Duration.addTo(referenceDate) or java.sql.Time(durationInMillis) . 如果这不是一个选择,则可以使用类似的逻辑,并将持续时间表示为相对于某个时间戳的偏移量,例如1970-01-01T00:00:00.000Z使用Duration.addTo(referenceDate)java.sql.Time(durationInMillis) To obtain an instance of Duration again you will need to use Duration.ofMillis(sqlTime.getTime()) . 要再次获取Duration的实例,您将需要使用Duration.ofMillis(sqlTime.getTime())

These are basically the options you have: 这些基本上是您可以选择的选项:

Using BIGINT as column type (preferred solution): 使用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);
        ...
    }
}

Using TIME or TIMESTAMP as column type. 使用TIMETIMESTAMP作为列类型。 You can replace java.sql.Time with java.sql.Timestamp in the below code depending on your actual column type: 您可以根据实际的列类型在以下代码中用java.sql.Timestamp替换java.sql.Time

// 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());
        ...
    }
}

According to MySQL's documentation the TIME type supports ranges from -838:59:59 to 838:59:59 (see here ). 根据MySQL的文档, TIME类型支持的范围是-838:59:59838:59:59 (请参阅此处 )。 But by default none of the types TIME , DATE or TIMESTAMP support fractional seconds unless the desired precision has been specified at creation time of the database columns (see here ). 但是默认情况下,除非在数据库列的创建时指定了所需的精度,否则TIMEDATETIMESTAMP类型都不支持小数秒(请参阅此处 )。 That is to store milliseconds in a TIME column, the table needs to be created like this: 也就是说要在TIME列中存储毫秒,需要像这样创建表:

CREATE TABLE t1 (t TIME(3));

Update: 更新:

  • Added more detailed code examples 添加了更详细的代码示例
  • Added link to MySQL documentation regarding the supported min max values for TIME 添加了指向MySQL文档的链接,其中涉及有关TIME的受支持的最小最大值

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM