localdatetime转化为date_关于datetime:在java.time.LocalDateTime和java.util.Date之间进行转换...

Java 8有一个全新的日期和时间API。 此API中最有用的类之一是LocalDateTime,用于保存与时区无关的date-with-time值。

为此目的,可能有数百万行代码使用遗留类java.util.Date。 因此,当连接新旧代码时,需要在两者之间进行转换。 由于似乎没有直接的方法来实现这一点,怎么办呢?

请参见http://stackoverflow.com/questions/33066904/simpliest-java8-localdate-to-java-util-date-conversion-and-vice-versa

docs.oracle.com/javase/tutorial/datetime/iso/legacy.html

Convert java.util.Date可能重复到java.time.LocalDate

简短回答:

Date in = new Date();

LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());

Date out = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());

说明:

(基于这个关于LocalDate的问题)

尽管它的名字,java.util.Date代表时间线上的瞬间,而不是"日期"。存储在对象中的实际数据是自1970-01-01T00:00Z(格林威治标准时间1970 /格林威治标准时间1970年初午夜)以来的long毫秒计数。

JSR-310中java.util.Date的等价类是Instant,因此有方便的方法来提供转换:

Date input = new Date();

Instant instant = input.toInstant();

Date output = Date.from(instant);

java.util.Date实例没有时区概念。如果在java.util.Date上调用toString(),这可能看起来很奇怪,因为toString是相对于时区的。但是,该方法实际上使用Java的默认时区来提供字符串。时区不是java.util.Date的实际状态的一部分。

Instant也不包含有关时区的任何信息。因此,要从Instant转换为本地日期时间,必须指定时区。这可能是默认区域 - ZoneId.systemDefault() - 或者它可能是应用程序控制的时区,例如来自用户首选项的时区。 LocalDateTime有一个方便的工厂方法,可以同时使用即时区和时区:

Date in = new Date();

LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());

反之,通过调用atZone(ZoneId)方法指定LocalDateTime时区。然后可以将ZonedDateTime直接转换为Instant:

LocalDateTime ldt = ...

ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault());

Date output = Date.from(zdt.toInstant());

请注意,从LocalDateTime到ZonedDateTime的转换可能会引入意外行为。这是因为夏令时不会存在每个本地日期时间。在秋季/秋季,当地时间线存在重叠,其中相同的本地日期时间出现两次。在春天,有一个缺口,一小时消失。有关转换将执行的更多定义,请参阅atZone(ZoneId)的Javadoc。

总结一下,如果您将java.util.Date往返到LocalDateTime并返回到java.util.Date,由于夏令时,您可能会得到不同的瞬间。

附加信息:还有另一个区别会影响很久的日期。 java.util.Date使用的日历在1582年10月15日更改,日期之前使用Julian日历而不是Gregorian日历。相比之下,java.time.*始终使用ISO日历系统(相当于格里高利)。在大多数用例中,ISO日历系统是您想要的,但在比较1582年之前的日期时,您可能会看到奇怪的效果。

非常感谢您的明确解释。特别是为什么java.util.Date不包含时区,而是在toString()期间打印它。活动官方文档在您发布时并未明确说明。

警告:LocalDateTime.ofInstant(date.toInstant()...表现不像人们想象的那样。例如,new Date(1111-1900,11-1,11,0,0,0);将使用此方法变为1111-11-17 23:53:28。如果在上一个示例中需要结果为1111-11-11 00:00:00,请查看java.sql.Timestamp#toLocalDateTime()的实现。

我添加了一个关于非常古老的日期(1582年之前)的部分。 FWIW,您建议的修复可能是错误的,因为java.util.Date中的1111-11-11与java.time中的1111-11-18历史相同,因为不同的日历系统(6.5分钟差异)发生在1900年之前的许多时区)

另外值得注意的是java.sql.Date#toInstant会抛出UnsupportedOperationException。所以不要在java.sql.ResultSet#getDate的RowMapper中使用toInstant。

这就是我想出来的(和所有日期时间难题一样,它可能会因为一些奇怪的时区 - 白昼 - 日光调整而被反驳:D)

往返:Date << - >> LocalDateTime

鉴于:Date date = [some date]

(1)LocalDateTime << Instant << Date

Instant instant = Instant.ofEpochMilli(date.getTime());

LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);

(2)Date << Instant << LocalDateTime

Instant instant = ldt.toInstant(ZoneOffset.UTC);

Date date = Date.from(instant);

例:

鉴于:

Date date = new Date();

System.out.println(date +" long:" + date.getTime());

(1)LocalDateTime << Instant << Date:

从Date创建Instant:

Instant instant = Instant.ofEpochMilli(date.getTime());

System.out.println("Instant from Date:

" + instant);

从Instant创建Date(不是必需的,但为了说明):

date = Date.from(instant);

System.out.println("Date from Instant:

" + date +" long:" + date.getTime());

从Instant创建LocalDateTime

LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);

System.out.println("LocalDateTime from Instant:

" + ldt);

(2)Date << Instant << LocalDateTime

从LocalDateTime创建Instant:

instant = ldt.toInstant(ZoneOffset.UTC);

System.out.println("Instant from LocalDateTime:

" + instant);

从Instant创建Date:

date = Date.from(instant);

System.out.println("Date from Instant:

" + date +" long:" + date.getTime());

输出是:

Fri Nov 01 07:13:04 PDT 2013 long: 1383315184574

Instant from Date:

2013-11-01T14:13:04.574Z

Date from Instant:

Fri Nov 01 07:13:04 PDT 2013 long: 1383315184574

LocalDateTime from Instant:

2013-11-01T14:13:04.574

Instant from LocalDateTime:

2013-11-01T14:13:04.574Z

Date from Instant:

Fri Nov 01 07:13:04 PDT 2013 long: 1383315184574

我认为这不像你想象的那么大。使用java.util.Date的旧代码从未依赖于java.time库,如果没有它,可能会很好。对于许多商店而言,改变新API的需求可能不是一个高优先级。新代码可以从头使用新的API。边缘情况是使用旧的内部或第三方库的新代码,它们产生Date s的结果,需要使用java.time与新代码交互。我认为这种情况并不常见。

@scottb你是在向我或提出问题的人发表这个问题吗?至于我的想法,那么在jdk 8 API中明确说明转换会很好 - 他们至少可以做到这一点。无论如何,有许多库将被重新考虑以包含新的Java-8功能,并且知道如何做到这一点非常重要。

@scottb为什么第三方案件不常见?它该死的常见。一个例子:JDBC 4和更少(希望不是5)。

作为一般的JSR-310规则,不需要使用epoch-millis在类型之间进行转换。使用对象存在更好的选择,请参阅下面的完整答案。如果使用像UTC这样的区域偏移,上面的答案也是完全有效的 - 答案的某些部分不适用于像America / New_York这样的完整时区。

而不是Instant.ofEpochMilli(date.getTime())做date.toInstant()

如果您确定需要默认时区,那么更方便的方法:

Date d = java.sql.Timestamp.valueOf( myLocalDateTime );

当然,它更容易,但我不喜欢混合jdbc相关的东西与简单的日期处理,至少恕我直言。

对不起,这是解决一个简单问题的可怕办法。这就像定义5等于奥林匹克标志中的戒指数量。

从新的API LocalDateTime转换为java.util.date时,以下似乎有效:

Date.from(ZonedDateTime.of({time as LocalDateTime}, ZoneId.systemDefault()).toInstant());

反向转换可以(希望)以类似的方式实现......

希望能帮助到你...

一切都在这里:http://blog.progs.be/542/date-to-java-time

"往返"的答案并不准确:当你这样做时

LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);

如果您的系统时区不是UTC / GMT,则更改时间!

只有你每年1小时,秋天,当LocalDateTime重叠两次时才这样做。弹簧向前移动不会引起问题。大多数时候都会正确转换两个方向。

我不确定这是最简单或最好的方式,还是有任何陷阱,但它有效:

static public LocalDateTime toLdt(Date date) {

GregorianCalendar cal = new GregorianCalendar();

cal.setTime(date);

ZonedDateTime zdt = cal.toZonedDateTime();

return zdt.toLocalDateTime();

}

static public Date fromLdt(LocalDateTime ldt) {

ZonedDateTime zdt = ZonedDateTime.of(ldt, ZoneId.systemDefault());

GregorianCalendar cal = GregorianCalendar.from(zdt);

return cal.getTime();

}

从LocalDateTime到Date肯定存在一个陷阱。在夏令时转换时,LocalDateTime可能不存在,或发生两次。你需要弄清楚你想要在每种情况下发生什么。

BTW,GregorianCalendar属于新的java.time API旨在取代的旧的尴尬API

LocalDateTime - > Date的最快方法是:

Date.from(ldt.toInstant(ZoneOffset.UTC))

如果您使用的是android并使用threetenbp,则可以使用DateTimeUtils。

例如:

Date date = DateTimeUtils.toDate(localDateTime.atZone(ZoneId.systemDefault()).toInstant());

您不能使用Date.from,因为它仅支持api 26+

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值