如何将 java.time.LocalTime 以毫秒映射到 java.sql.Time 以毫秒

How to map java.time.LocalTime with milliseconds to a java.sql.Time with miliseconds

如何将带秒 (micro/milli/nano) 的 java.time.LocalTime 转换为 java.sql.Time

我知道自从 spring-data-jpa 的 2.x 版本以来,那些类型 (JSR310) 有它们的自定义转换器映射到遗留 java.sql.Datejava.sql.Timestamp 但我有LocalTime 第二部分的分数有很多问题。

How to map java.time.LocalTime to a java.sql.Time

这是一种不使用 String 作为中间值的方法。

java.time.LocalTime localTime = java.time.LocalTime.now();
long epochMilli = localTime.atDate(java.time.LocalDate.EPOCH)
                           .atZone(java.time.ZoneId.systemDefault())
                           .toInstant()
                           .toEpochMilli();
java.sql.Time sqlTime = new java.sql.Time(epochMilli);

System.out.println(localTime.format(DateTimeFormatter.ofPattern("HH:mm:ss.SSS")));
System.out.println(new SimpleDateFormat("HH:mm:ss.SSS").format(sqlTime));

输出

22:28:22.104
22:28:22.104

根本问题是当地时间代表一天中的特定时间:

例如7:30pm

不是 7:30pm今天或昨天,或从星期天算起的第十七周,就... 7:30pm.

而 java.sql.Time 表示特定日期的特定时间

它们在内部存储为 long,即特定日期之前或之后的毫秒数(IIRC 1970 年 1 月 1 日)。

因此,要将 LocalTime 转换为 java.sql.Time,您必须指定该时间适用的特定日期。

查看 LocalTime.atDate(LocalDate),其中 returns 一个 LocalDateTime。

似乎没有一个很好的简单方法来提取毫秒或 net 纳秒(自 1/1/1970 00:00:00)

也许尝试 .toEpochSecond(需要指定时区),然后将其乘以 1000 或 1000000,然后将其写入数据库,然后将其读回(以查看是否有效)。


或者:

你一直说你不想要日期 - 我明白了,但由于数据库不需要,你可以尝试存储 localTime.toNanoOfDay.

它将解释为 1/1/1970 的一天中的某个时间。

很可能您不希望从 LocalTime 转换为老式的 Time

如果您认为您需要一个 java.sql.Time 来存储到您的 SQL 数据库或对其进行查询,情况可能并非如此。如果您至少可以使用 Java 8 和至少 JDBC 4.2(或现代 JPA 实现),则可以直接对数据库使用 LocalTime 而无需转换。使用例如

    yourPreparedStatement.setObject(7, yourLocalTime);

那你就没事了

如果您确实需要 java.sql.Time shows the right and precise way to convert. The challenge is that the simple Time.valueOf(LocalTime) loses the fraction of second. The docs,请说:

The nanosecond field from LocalTime is not part of the newly created Time object.

很明显,你不能拥有所有的纳秒,因为 Time 只有毫秒的精度。为什么他们不取毫秒(9 位纳秒值的前 3 位十进制数字),我不知道。安德烈亚斯。