将 LocalDate 转换为 LocalDateTime 或 java.sql.Timestamp

Posted

技术标签:

【中文标题】将 LocalDate 转换为 LocalDateTime 或 java.sql.Timestamp【英文标题】:Convert LocalDate to LocalDateTime or java.sql.Timestamp 【发布时间】:2012-02-18 00:30:46 【问题描述】:

我正在使用 JodaTime 1.6.2。

我有一个 LocalDate,我需要将其转换为 (Joda) LocalDateTimejava.sqlTimestamp 以进行映射。

原因是我已经弄清楚如何在 LocalDateTimejava.sql.Timestamp 之间进行转换:

LocalDateTime ldt = new LocalDateTime();
DateTimeFormatter dtf = DateTimeFormatter.forPattern("yyyy-MM-dd HH:mm:ss");
Timestamp ts = Timestamp.valueOf(ldt.toString(dtf));

所以,如果我可以在LocalDateLocalDateTime 之间进行转换,那么我可以继续转换为java.sql.Timestamp。感谢您在正确方向上的任何推动!

【问题讨论】:

仅供参考,Joda-Time 项目现在位于maintenance mode,团队建议迁移到java.time 类。见Tutorial by Oracle。此外,java.sql.Timestamp 类现在是遗留的,被 java.time 类取代,特别是被Instant 【参考方案1】:

乔达时间

要将 JodaTime 的 org.joda.time.LocalDate 转换为 java.sql.Timestamp,只需这样做

Timestamp timestamp = new Timestamp(localDate.toDateTimeAtStartOfDay().getMillis());

要将 JodaTime 的 org.joda.time.LocalDateTime 转换为 java.sql.Timestamp,只需这样做

Timestamp timestamp = new Timestamp(localDateTime.toDateTime().getMillis());

Java时间

要将 Java8 的 java.time.LocalDate 转换为 java.sql.Timestamp,只需这样做

Timestamp timestamp = Timestamp.valueOf(localDate.atStartOfDay());

要将 Java8 的 java.time.LocalDateTime 转换为 java.sql.Timestamp,只需这样做

Timestamp timestamp = Timestamp.valueOf(localDateTime);

【讨论】:

在将LocalDateTime 转换为DateTime 时要小心,因为并非所有LocalDateTimes 都是有效的DateTimes。来源:joda-time.sourceforge.net/faq.html#illegalinstant 刚刚碰到这个。 在 valueOf() 接受字符串时出现参数编译错误。 @Patriotic:只有在您实际上没有使用 Java SE 1.8 或更高版本时才会发生这种情况。如答案和提供的 Javadoc 链接中所示(上面答案中的蓝色文本实际上是链接,您可以单击它们以深入了解 Javadoc),Timestamp#valueOf() 方法自 Java SE 1.8 起接受 @987654347 @. java.lang.IllegalArgumentException: 时间戳格式必须是 yyyy-mm-dd hh:mm:ss[.fffffffff];;;;我做Timestamp.valueOf(Timestamp(longtimestampppp).toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().toString()) 只要按照答案中的最后一个示例,而不是无缘无故地对其进行toString()【参考方案2】:

使用 Java 8 time API 的最佳方式:

  LocalDateTime ldt = timeStamp.toLocalDateTime();
  Timestamp ts = Timestamp.valueOf(ldt);

用于与您的模型一起放入的 JPA (https://weblogs.java.net/blog/montanajava/archive/2014/06/17/using-java-8-datetime-classes-jpa):

@Converter(autoApply = true)
public class LocalDateTimeConverter implements AttributeConverter<LocalDateTime, Timestamp> 
    @Override
    public Timestamp convertToDatabaseColumn(LocalDateTime ldt) 
        return Timestamp.valueOf(ldt);
    

    @Override
    public LocalDateTime convertToEntityAttribute(Timestamp ts) 
        return ts.toLocalDateTime();
    

所以现在是相对时区独立时间。 此外,它很容易做到:

  LocalDate ld = ldt.toLocalDate();
  LocalTime lt = ldt.toLocalTime();

格式:

 DateTimeFormatter DATE_TME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
 String str = ldt.format(DATE_TME_FORMATTER);
 ldt = LocalDateTime.parse(str, DATE_TME_FORMATTER);

更新:postgres 9.4.1208、HSQLDB 2.4.0 等无需任何对话即可理解 Java 8 Time API!

【讨论】:

有人可以帮我解决这个问题吗?它不工作***.com/questions/69533213/…@BalusC【参考方案3】:

tl;博士

Joda-Time 项目处于维护模式,现在被 java.time 类取代。

只需使用java.time.Instant 类。 不需要: LocalDateTime java.sql.Timestamp 字符串

以 UTC 捕获当前时刻。

Instant.now()  

将该时刻存储在数据库中:

myPreparedStatement.setObject( … , Instant.now() )  // Writes an `Instant` to database.

从数据库中检索那个时刻:

myResultSet.getObject( … , Instant.class )  // Instantiates a `Instant`

将挂钟时间调整为特定时区的时间。

instant.atZone( z )  // Instantiates a `ZonedDateTime`

LocalDateTime 是错误的类

其他答案是正确的,但他们没有指出 LocalDateTime 是错误的类。

java.timeJoda-Time 中,LocalDateTime 故意缺少任何时区或与 UTC 偏移的概念。因此,它确实代表一个时刻,并且不是时间线上的一个点。 LocalDateTime 代表关于大约 26-27 小时范围内潜在时刻的粗略概念。

当区域/偏移量未知(不是很好的情况)或区域偏移量不确定时,使用LocalDateTime。例如,“圣诞节从 2018 年 12 月 25 日的第一刻开始”将表示为 LocalDateTime

使用ZonedDateTime 表示特定时区的某个时刻。例如,在Pacific/AucklandAmerica/Montreal 等任何特定区域开始的圣诞节将用ZonedDateTime 对象表示。

暂时始终使用 UTC,请使用 Instant

Instant instant = Instant.now() ;  // Capture the current moment in UTC.

应用时区。同一时刻,时间轴上的同一点,但以不同的挂钟时间查看。

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;  // Same moment, different wall-clock time.

所以,如果我可以在 LocalDate 和 LocalDateTime 之间进行转换,

不,错误的策略。如果您有仅日期值,并且需要日期时间值,则必须指定时间。对于特定区域,该时间可能在该日期无效 - 在这种情况下,ZonedDateTime 类会根据需要自动调整时间。

LocalDate ld = LocalDate.of( 2018 , Month.JANUARY , 23 ) ;
LocalTime lt = LocalTime.of( 14 , 0 ) ;  // 14:00 = 2 PM.
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;

如果您想将一天中的第一个时刻作为您的时间,让 java.time 确定那个时刻。不要假设一天从 00:00:00 开始。夏令时 (DST) 等异常情况意味着一天可能从另一个时间开始,例如 01:00:00。

ZonedDateTime zdt = ld.atStartOfDay( z ) ;

java.sql.Timestamp 是错误的类

java.sql.Timestamp 是麻烦的旧日期时间类的一部分,这些类现在已经遗留,完全被 java.time 类所取代。该类用于表示UTC 中的一个时刻,分辨率为nanoseconds。现在,java.time.Instant 可以实现这一目的。

JDBC 4.2 与 getObject/setObject

从JDBC 4.2 及以后,您的JDBC driver 可以通过调用直接与数据库交换java.time 对象:

PreparedStatement::setObject ResultSet::getObject

例如:

myPreparedStatement.setObject( … , instant ) ;

……和……

Instant instant = myResultSet.getObject( … , Instant.class ) ;

转换传统 ⬌ 现代

如果您必须与尚未更新到 java.time 的旧代码交互,请使用添加到旧类的新方法来回转换。

Instant instant = myJavaSqlTimestamp.toInstant() ;  // Going from legacy class to modern class.

……和……

java.sql.Timestamp myJavaSqlTimestamp = java.sql.Timestamp.from( instant ) ;  // Going from modern class to legacy class.

关于java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。

您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。

从哪里获得 java.time 类?

Java SE 8Java SE 9 及更高版本 内置。 标准 Java API 的一部分,带有捆绑实现。 Java 9 添加了一些小功能和修复。 Java SE 6Java SE 7 大部分 java.time 功能都在ThreeTen-Backport 中向后移植到 Java 6 和 7。 Android java.time 类的 android 捆绑包实现的更高版本。 对于早期的 Android (ThreeTenABP 项目采用 ThreeTen-Backport(如上所述)。见How to use ThreeTenABP…

ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuarter 和more。

【讨论】:

【参考方案4】:

根据您的时区,您可能会损失几分钟(1650-01-01 00:00:00 变为 1649-12-31 23:52:58)

使用下面的代码来避免这种情况

new Timestamp(localDateTime.getYear() - 1900, localDateTime.getMonthOfYear() - 1, localDateTime.getDayOfMonth(), localDateTime.getHourOfDay(), localDateTime.getMinuteOfHour(), localDateTime.getSecondOfMinute(), fractional);

【讨论】:

【参考方案5】:

java.time.LocalDate 对象的函数调用asStartOfDay() 返回一个java.time.LocalDateTime 对象

【讨论】:

【参考方案6】:

由于 Joda 逐渐消失,有人可能希望在 Java 8 中将 LocaltDate 转换为 LocalDateTime。在 Java 8 中,LocalDateTime 将提供一种使用 LocalDate 和 @ 创建 LocalDateTime 实例的方法987654330@。检查here.

public static LocalDateTime of(LocalDate date, 本地时间)

示例是,

    // just to create a sample LocalDate
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");
    LocalDate ld = LocalDate.parse("20180306", dtf);

    // convert ld into a LocalDateTime
    // We need to specify the LocalTime component here as well, it can be any accepted value
    LocalDateTime ldt = LocalDateTime.of(ld, LocalTime.of(0,0)); // 2018-03-06T00:00

仅供参考,获取下面的纪元秒数可以使用,

    ZoneId zoneId = ZoneId.systemDefault();
    long epoch = ldt.atZone(zoneId).toEpochSecond(); 

    // If you only care about UTC
    long epochUTC = ldt.toEpochSecond(ZoneOffset.UTC);

【讨论】:

这里根本不需要使用LocalDateTime。该类故意缺少任何时区或与 UTC 偏移的概念。所以它在这里没有用处。相反:LocalDate.parse( “20180306” , DateTimeFormatter.BASIC_ISO_DATE ).atStartOfDay( ZoneId.of( “Africa/Tunis” ).toEpochSecond() 不要假设一天从 00:00 开始,并非总是如此。 你的意思是什么不要假设一天从 00.00 开始 Daylight Saving Time (DST) 等异常意味着在某些地方的某些日期,一天可能从另一个时间开始,例如 01:00:00。因此,与其假设,不如让 java.time 通过调用java.time.LocalDate.atStartOfDay 来确定第一个时刻以获取ZonedDateTime。请参阅my Answer 中的示例。正如我所评论的那样,LocalDateTime 类在这一切中都是无用的并且适得其反。 所以对于LocalDateTime,我们必须使用ZoneId ? 我认为你错过了我的所有观点。在此页面上重新阅读我的答案。搜索 Stack Overflow 以从更多示例和讨论中了解更多信息。但我会在这里最后一次说:LocalDateTime 适合手头的问题。 LocalDateTime 确实代表片刻。 LocalDateTime与任何特定的地区或时区无关,尽管名称乍一看可能暗示其他含义 - 了解有关本课程的意图和详细信息的更多信息。 LocalDateTime 类确实有目的,但不是本问题中看到的目的。【参考方案7】:

Java8 +

import java.time.Instant;
Instant.now().getEpochSecond(); //timestamp in seconds format (int)
Instant.now().toEpochMilli(); // timestamp in milliseconds format (long)

【讨论】:

有用,但似乎并不能真正回答问题。 感谢代码,但与问题无关。

以上是关于将 LocalDate 转换为 LocalDateTime 或 java.sql.Timestamp的主要内容,如果未能解决你的问题,请参考以下文章

如何将 Joda Localdate 转换为 Joda DateTime?

将 LocalDate 转换为 LocalDateTime 或 java.sql.Timestamp

如何将 Javascript 日期转换为 Spring @RequestParam 的 LocalDate?

如何在不使用 DateTimeFormatter 的情况下将字符串转换为 LocalDate [重复]

将通过 JDBC 检索到的 java.sql.Date 值转换为 java.time.LocalDate? [复制]

Spring Data - 如何将 YearMonth 类型的 @Param 转换为 LocalDate 的开始和结束?