Java的8对日期和时间的全新API。 这其中一个API中最有用的类是LocalDateTime
,用于保存时区无关的日期与时间值。
可能有上百万使用传统类的代码行java.util.Date
用于这一目的。 因此,接口新旧代码的时候会有需要在两者之间转换。 因为似乎是实现这个没有直接的方法,怎么能做到呢?
Java的8对日期和时间的全新API。 这其中一个API中最有用的类是LocalDateTime
,用于保存时区无关的日期与时间值。
可能有上百万使用传统类的代码行java.util.Date
用于这一目的。 因此,接口新旧代码的时候会有需要在两者之间转换。 因为似乎是实现这个没有直接的方法,怎么能做到呢?
简短的回答:
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
代表在时间线的瞬间,而不是一个“约会”。 存储在对象内的实际数据是一个long
,因为1970-01-01T00毫秒计数:00Z(在1970 GMT / UTC的开始午夜)。
等效类java.util.Date
在JSR-310是Instant
,从而有方便的方法,以提供转换来回:
Date input = new Date();
Instant instant = input.toInstant();
Date output = Date.from(instant);
一个java.util.Date
实例没有时区的概念。 这如果调用可能很陌生toString()
上java.util.Date
,因为toString
是相对于一个时区。 但是,这种方法实际使用的飞行Java的默认时区提供的字符串。 该时区不实际状态的一部分java.util.Date
。
一个Instant
还没有关于时区的任何信息。 因此,从一个转换Instant
到本地日期时间,需要指定一个时区。 这可能是默认区域- ZoneId.systemDefault()
-或者它可能是一个时区,您的应用程序的控制,如用户偏好的时区。 LocalDateTime
有一个方便的工厂方法,它采用两个即时和时区:
Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
在倒车时,所述LocalDateTime
的时区是通过调用指定atZone(ZoneId)
方法。 所述ZonedDateTime
然后可以直接转换为Instant
:
LocalDateTime ldt = ...
ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault());
Date output = Date.from(zdt.toInstant());
注意,从转换LocalDateTime
到ZonedDateTime
有引进意外行为的可能性。 这是因为不是每个地方的日期 - 时间由于夏令时存在。 在秋天/下降,存在在相同的本地日期时间发生两次的本地时间线的重叠。 在弹簧,有一个间隙,其中一个小时消失。 看到的Javadoc atZone(ZoneId)
更多的东西转换将做定义。
总之,如果你来回一个java.util.Date
的LocalDateTime
和回java.util.Date
你可以用不同的瞬间,由于夏令时结束。
附加信息:还有一个区别,这将影响很老的日期。 java.util.Date
使用,在此之前使用的儒略历,而不是公历一个变化在1582年10月15日,有日期的日历。 相比之下, java.time.*
使用所有的时间了ISO日历系统(相当于公历)。 在大多数使用情况下,ISO日历系统是你想要的,但1582年之前比较日期时,您可能会看到奇怪的效果。
以下是我想出了(像所有日期时间谜题它很可能将基于一些奇怪的时区,leapyear白昼调整被反驳: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());
LocalDateTime
<< Instant
<< Date
: 创建Instant
从Date
:
Instant instant = Instant.ofEpochMilli(date.getTime());
System.out.println("Instant from Date:\n" + instant);
创建Date
从Instant
(不是必须的,但为了举例说明):
date = Date.from(instant);
System.out.println("Date from Instant:\n" + date + " long: " + date.getTime());
创建LocalDateTime
从Instant
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
System.out.println("LocalDateTime from Instant:\n" + ldt);
Date
<< Instant
<< LocalDateTime
创建Instant
从LocalDateTime
:
instant = ldt.toInstant(ZoneOffset.UTC);
System.out.println("Instant from LocalDateTime:\n" + instant);
创建Date
从Instant
:
date = Date.from(instant);
System.out.println("Date from Instant:\n" + 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
更方便的方法,如果你确信你需要一个默认的时区:
Date d = java.sql.Timestamp.valueOf( myLocalDateTime );
下面似乎和新的API LocalDateTime转换成java.util.date时的工作:
Date.from(ZonedDateTime.of({time as LocalDateTime}, ZoneId.systemDefault()).toInstant());
反向转换可以是(希望)实现类似的方式...
希望能帮助到你...
我不知道这是最简单的或最好的办法,或者有任何缺陷,但是它的工作原理:
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();
}
一切都在这里: http://blog.progs.be/542/date-to-java-time
用“往返”答案是不准确的:当你做
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
如果你的系统的时区不是UTC / GMT,你改变的时候了!
如果你是Android和使用threetenbp可以使用DateTimeUtils
代替。
例如:
Date date = DateTimeUtils.toDate(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
你不能使用Date.from
因为它仅支持API 26+
为以最快的方式LocalDateTime
- > Date
是:
Date.from(ldt.toInstant(ZoneOffset.UTC))