我需要从具有日期和时间两个部分的LocalDateTime转换为Date而又不损失时间部分。我一直在做类似的事情:
LocalDateTime ldt = //some full date-time value
Date date = java.util.Date.valueOf(ldt.toLocalDate());
,但是显然丢失了时间部分。.我看到还有一个LocalDateTime.toLocalTime(),但是我需要日期和时间在一起。
谢谢
答案 0 :(得分:4)
这是因为java.sql.Date
不包括时间。
您可以改用java.sql.Timestamp
类,其中包括日期和时间。
答案 1 :(得分:0)
java.util.Date
会保留时间分量(如果您提供的话)。但是首先,您为什么要使用旧的Date而不是新的Java 8 java.time
包?无论如何要回答您的问题,我建议检索纪元毫秒,然后从中创建您的Date
。所以看起来像这样:
long epoch = ZonedDateTime.of(ldt, ZoneId.systemDefault()).toInstant().toEpochMilli();
Date date = new Date(epoch);
由于Basil Bourque的要求-解释为什么需要ZonedDateTime
:为了提取时代-从“ 1.1.1970 00:00:00 + 0000”起的毫秒数,您将需要转换{{ 1}}(不是绝对时间,可能意味着在不同位置的时间不同)到LocalDateTime
,它也保存一个位置,因此是绝对时间。因此,您可以从ZonedDateTime
中提取纪元。
答案 2 :(得分:0)
显然,您无意中使用了您认为正在使用java.sql.Date
的类java.util.Date
。但是这个问题没有解决:使用 java.time 类,而不是那些糟糕的旧日期时间类。
myPreparedStatement.setObject( … , myLocalDateTime ) ;
…和…
myResultSet.getObject( … , LocalDateTime.class )
很显然,您无意中使用了java.sql.Date
,它假装没有一天的时间。不幸的是,可怕的类设计继承自java.util.Date
,它确实有一天的时间。因此sql
将其时间设置为00:00:00。并且文档告诉我们忽略它们继承的事实。糟糕的设计,糟糕的名字和周围可怕的阶级。
由于所有这些原因以及更多原因,这些旧类在几年前被 java.time 类所取代。
从JDBC 4.2开始,我们可以与数据库交换 java.time 类。无需再次触摸java.util.Date
,java.sql.Date
,java.sql.Timestamp
。
LocalDateTime
应该存储在类似于SQL标准类型TIMESTAMP WITHOUT TIME ZONE
的数据库列中。这些类型有意缺少时区或从UTC偏移的任何概念。因此,这些类型不能代表一个时刻,不能在时间轴上保留特定点。在大多数业务场景中,这些可能不是。
myPreparedStatement.setObject( … , myLocalDateTime ) ;
检索:
myLocalDateTime = myResultSet.getObject( … , LocalDateTime.class ) ;
如果它们不能代表片刻,那么这些类型有什么用?在什么情况下使用java.time.LocalDateTime
类和TIMESTAMP WITHOUT TIME ZONE
列是合适的?这三个:
LocalDateTime
。要打印报告或显示日历,请动态应用时区(ZoneId
)以生成特定时刻(ZonedDateTime
或Instant
)。此操作必须即时完成,而不是存储值。相反,要存储时刻,请使用类似于SQL标准类型TIMESTAMP WITH TIME ZONE
的数据库列。对于此类列,在Java中使用Instant
类。此类表示UTC中的时刻,分辨率为nanoseconds。
myPreparedStatement.setObject( … , myInstant ) ;
检索:
myInstant = myResultSet.getObject( … , Instant.class ) ;
如果您确定LocalDateTime
是隐式表示特定地区(时区)的人们在墙上时钟中使用的时刻,请应用ZoneId
以获得一个ZonedDateTime
。
以continent/region
的格式指定proper time zone name,例如America/Montreal
,Africa/Casablanca
或Pacific/Auckland
。切勿使用3-4个字母的缩写,例如EST
或IST
,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。
ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime zdt = myLocalDateTime.atZone( z ) ;
然后提取一个Instant
对象以调整为UTC。
Instant instant = zdt.toInstant();
存储在数据库中。
myPreparedStatement.setObject( … , instant ) ;
从数据库检索。
Instant instant = myResultSet.getObject( … , Instant.class ) ;
java.time框架已内置在Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和SimpleDateFormat
。
目前位于Joda-Time的maintenance mode项目建议迁移到java.time类。
要了解更多信息,请参见Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310。
您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*
类。
在哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如Interval
,YearWeek
,YearQuarter
和more。