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


126

我正在使用JodaTime 1.6.2。

我有一个LocalDate需要转换为(Joda)LocalDateTimejava.sqlTimestampfor ormapping的。

原因是我想出了如何在a LocalDateTime和a 之间进行转换java.sql.Timestamp

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

因此,如果我可以在LocalDate和之间进行转换LocalDateTime,则可以继续转换为java.sql.Timestamp。感谢您朝着正确的方向前进!


仅供参考,Joda-Time项目现在处于维护模式,团队建议迁移到java.time类。请参见Oracle教程。而且,java.sql.Timestamp该类现在是旧式的,由java.time类(尤其是)取代了Instant
罗勒·布尔克

Answers:


269

乔达时间

要将JodaTime转换org.joda.time.LocalDatejava.sql.Timestamp,只需执行

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

要将JodaTime转换org.joda.time.LocalDateTimejava.sql.Timestamp,只需执行

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

Java时间

要将Java8转换java.time.LocalDatejava.sql.Timestamp,只需执行

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

要将Java8转换java.time.LocalDateTimejava.sql.Timestamp,只需执行

Timestamp timestamp = Timestamp.valueOf(localDateTime);

转换为时请当心LocalDateTimeDateTime因为并非所有LocalDateTimes都有效DateTime。资料来源:joda-time.sourceforge.net/faq.html#illegalinstant,并且正好遇到了这个问题。
Christophe De Troyer

由于valueOf()接受字符串,导致参数出现编译错误。
爱国

@Patriotic:只有在您实际上不使用Java SE 1.8或更高版本时,才会发生这种情况。如答案中所示,并在指向Javadoc的链接中提供了答案(上述答案中的蓝色文本实际上是链接,您可以单击它们以深入到Javadoc中),该Timestamp#valueOf()方法接受,因为Java SE 1.8也是a LocalDateTime
BalusC

60

使用Java 8时间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!


17

tl; dr

乔达时间项目处于维护模式,现在取代java.time类。

  • 只需使用java.time.Instant类。
  • 无需:
    • LocalDateTime
    • java.sql.Timestamp
    • 弦乐

在UTC中捕获当前时刻。

Instant.now()  

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

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

要从datbase检索该时刻:

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

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

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

LocalDateTime 是错误的班级

其他答案是正确的,但他们未能指出这LocalDateTime是您目的不正确的课程。

java.timeJoda-Time中LocalDateTime故意缺乏时区或UTC偏移量的任何概念。因此,它并不能代表一个时刻,是不是在时间轴上的一个点。A LocalDateTime代表关于大约26-27小时范围内潜在时刻的粗略想法。

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

使用a 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中具有纳秒分辨率的时刻。现在已达到该目的java.time.Instant

带有getObject/的JDBC 4.2setObject

JDBC 4.2及更高版本开始,您的JDBC驱动程序可以通过调用以下命令直接与数据库交换java.time对象:

例如:

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和更高版本。这些类取代麻烦的老传统日期时间类,如java.util.DateCalendar,和SimpleDateFormat

现在处于维护模式Joda-Time项目建议迁移到java.time类。

要了解更多信息,请参见Oracle教程。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310

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

在哪里获取java.time类?

ThreeTen-额外项目与其他类扩展java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。你可能在这里找到一些有用的类,比如IntervalYearWeekYearQuarter,和更多


5

根据您的时区,您可能会丢失几分钟(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);

3

由于乔达是越来越淡了,有人可能要转换LocaltDateLocalDateTimeJava中8在Java 8 LocalDateTime它将给一个方法来创建一个LocalDateTime使用实例LocalDateLocalTime在这里检查

公共静态LocalDateTime((LocalDate日期,LocalTime时间)

样本是

    // 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开始,并非总是如此。
罗勒·布尔克

您是说Whay的意思是,不要假设一天从00.00开始
黄金

1
诸如夏令时(DST)之类的异常表示一天在某些地方的某些日期可能会在另一时间开始,例如01:00:00。因此,而不是假设,让java.time通过调用java.time.LocalDate.atStartOfDayget 来确定第一时刻ZonedDateTime。请参阅我的答案中的示例。正如我所评论的那样,LocalDateTime该类在所有这些方面都是无用的且适得其反。
罗勒·布尔克

因此LocalDateTime必须使用ZoneId
黄金

我想你已经错过了我所有的观点。在此页面上重读我的答案。搜索堆栈溢出可从更多示例和讨论中了解更多信息。但我会说这里的最后一次:LocalDateTime不是在手拨出这里的问题。一个LocalDateTime不会表示一个时刻。尽管名称乍一看可能暗示其他名称,但A 与任何特定的地区LocalDateTime或时区没有关系 –了解有关此类的意图和细节的更多信息。该LocalDateTime班也服务于一个目的,但不是在这个问题上看到的目的。
罗勒·布尔克


0

Java8 +

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

有用,但似乎并未真正回答问题。
Ole VV

感谢您提供的代码,但与该问题无关。
refaelio
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.