java.util.Date和Zoneddatetime有什么区别? [英] Whats the difference between java.util.Date and Zoneddatetime?
问题描述
使用util.date并从浏览器给日期提供服务时间,然后保存到db并取回数据库时,会产生不同的日期时间,与直接从服务中设置zoneddatetime无关.
While using util.date and giving date with time to service from browser and then saving to db and taking it back it gives different date time against setting zoneddatetime directly from service.
任何帮助将不胜感激.
推荐答案
tl; dr
java.util.Date和Zoneddatetime有什么区别?
Whats the difference between java.util.Date and Zoneddatetime?
-
Date
代表UTC的时刻,而ZonedDateTime
代表特定时区的时刻. -
Date
是一个可怕的类,充满设计缺陷,不应该使用,而ZonedDateTime
是 java.time 包中的现代类,您会发现它非常有用. Date
represents a moment in UTC, whileZonedDateTime
represents a moment in a particular time zone.Date
is a terrible class, riddled with design flaws, that should never be used, whileZonedDateTime
is a modern class from the java.time package that you will find quite useful.-
java.util.Date
被替换为java.time.Instant
- 两者都代表UTC的时刻.
java.util.Date
was replaced byjava.time.Instant
- Both represent a moment in UTC.
- 两者都代表在特定时区看到的时刻.
Date
类表示UTC中的时刻.也就是说,日期,一天中的时间以及UTC的上下文.The
Date
class represents a moment in UTC. That is, a date, a time-of-day, plus the context of UTC.在内部,它是自1970年1月1日UTC的纪元参考日期1970-01-01T00:00:00Z以来的毫秒数.
Internally, it is a count of milliseconds since the epoch reference date of first moment of 1970 in UTC, 1970-01-01T00:00:00Z.
使事情复杂化:
- 创建时会捕获一个时区,该时区存储在内部,没有getter或setter.因此,尽管它确实适用于此类使用
equals
实现的问题,但在大多数情况下我们可以忽略此区域. - 在调用
toString
时,此类具有非常的令人困惑的行为,即在生成表示该对象值的文本时动态应用JVM的当前时区.尽管出于良好目的,但这种反功能却在试图学习日期时间处理的Java程序员中引起了难以估量的痛苦.
- There is a time zone capture upon creation, stored deep inside, without getters or setters. So for the most part we can ignore this zone, though it does apply for matters such has this class’ implementation of
equals
. - When calling
toString
this class has the very confusing behavior of dynamically applying the JVM’s current time zone while generating text to represent the value of this object. While well-intentioned, this anti-feature has caused incalculable pain among Java programmers trying to learn date-time handling.
困惑吗?是的,该类令人困惑,糟糕的设计决策混乱不堪.后来又添加了
java.util.Calendar
&GregorianCalendar
.Confused? Yes, this class is confusing, a wretched mess of poor design decisions. Compounded by the later addition of
java.util.Calendar
&GregorianCalendar
.与最早的Java版本捆绑在一起的所有这些麻烦的日期时间类现在都完全被 java.time 类所取代.
All of these troublesome date-time classes bundled with the earliest version of Java are now supplanted entirely by the java.time classes.
尤其是
java.util.Date
被java.time.Instant
代替.从1970年UTC时代开始,两者都代表UTC的时刻.但是Instant
具有更好的分辨率,纳秒而不是In particular,
java.util.Date
is replaced byjava.time.Instant
. Both represent a moment in UTC as count from the epoch of 1970 UTC. ButInstant
carries a finer resolution, nanoseconds rather than milliseconds.您可以通过调用添加到旧类中的新方法,在旧类
Date
和现代类Instant
之间来回转换.通常,您将避免使用Date
.但是当与尚未更新为 java.time 的旧代码接口时,您可能需要进行转换.You can convert back-and-forth between the legacy class
Date
and the modern classInstant
by calling new methods added to the old class. Usually, you will avoid ever usingDate
. But when interfacing with old code not yet updated to java.time, you may need to convert.现代类
ZonedDateTime
表示某个区域(时区)的人们在墙上时钟使用的时刻.The modern class
ZonedDateTime
represent a moment as seen in the wall-clock time used by the people of a certain region (a time zone).因此
Instant
和ZonedDateTime
相似之处在于它们都代表一个时刻,即该时间轴上的特定点.区别在于ZonedDateTime
知道时区的规则.因此,ZonedDateTime
知道如何解决诸如夏令时(DST)或政客要求的其他时间变更等异常情况.So
Instant
andZonedDateTime
are similar in that they both represent a moment, a specific point on that timeline. The difference is thatZonedDateTime
knows about the rules of a time zone. So aZonedDateTime
knows how to account for anomalies such as Daylight Saving Time (DST) or other changes to time-keeping required by politicians.您可以将其视为:
ZonedDateTime
=(Instant
+ZoneId
)通过对
Instant
对象应用时区(ZoneId
),我们可以轻松地从UTC调整到某个时区.We can easily adjust from UTC to some time zone by applying a time zone (
ZoneId
) to aInstant
object.Instant instant = Instant.now() ; // Capture the current moment as seen in UTC. ZoneId z = ZoneId.of( "Asia/Tokyo" ) ; ZonedDateTime zdt = instant.atZone( z ) ; // Apply a time zone to see the same moment through the wall-clock time in use by the people of a particular region (a time zone).
请参阅此在IdeOne.com上实时运行的代码.请注意不同的日期和不同的时间,但同时具有相同的时刻.
See this code run live at IdeOne.com. Note the different date and the different time-of-day, yet the same simultaneous moment.
instant.toString():2019-02-27T19:32:43.366Z
instant.toString(): 2019-02-27T19:32:43.366Z
zdt.toString():2019-02-28T04:32:43.366 + 09:00 [亚洲/东京]
zdt.toString(): 2019-02-28T04:32:43.366+09:00[Asia/Tokyo]
关键概念:
Instant
和ZonedDateTime
都表示同一时刻,时间轴上的同一同时点.它们的挂钟时间不同.例如,如果日本某人给冰岛某人打电话(一直使用UTC作为时钟),并且他们俩都抬头看着挂在各自墙上的时钟,他们会看到不同的时间,并且可能甚至每月日历上的另一个日期.相同的时刻,不同的时钟时间.Crucial concept:
Instant
andZonedDateTime
both represent the same moment, the same simultaneous point on the timeline. They differ in the wall-clock time. For example, if someone in Japan calls someone in Iceland (where UTC is used for their clocks all the time), and they both look up at the clock hanging on their respective walls, they will see a different time-of-day and possibly even a different date on the monthly calendar. Same moment, different wall-clock time.对于旧类,
ZonedDateTime
的等效项是java.util.Calendar
.实际上,旧类GregorianCalendar
获得了用于转换来自ZonedDateTime
.As for the legacy classes, the equivalent of
ZonedDateTime
isGregorianCalendar
, a concrete implementation ofjava.util.Calendar
. Indeed, the old classGregorianCalendar
gained new methods for conversion to/fromZonedDateTime
.ZonedDateTime zdt = myGregorianCalendar.toZonedDateTime(); // Convert from legacy to modern class.
…和…
GregorianCalendar gc = GregorianCalendar.from( zdt ) ; // Convert from modern to legacy class.
结论
因此,
Date
等同于Instant
,两者都是UTC时刻.但是ZonedDateTime
不同于这两者,因为时区通过应用区域人民的挂钟时间调整镜头来调整了对瞬间的感知.Conclusion
So a
Date
is equivalent to aInstant
, both being a moment in UTC. But aZonedDateTime
differs from both in that a time zone has adjusted the perception of the moment by applying the lens of a region’s people’s wall-clock time adjustment.提示:
- 切勿使用
Date
.交给Date
时,请立即转换为Instant
.然后继续您的业务逻辑. - 在UTC中完成大部分工作.跟踪时刻,调试,日志记录,交换日期时间值以及持久保存到数据库通常应该在UTC中完成.学会在从事程序员工作时忘记自己的时区.将您桌上的第二个时钟设置为UTC.
- Never use
Date
. When handed aDate
, immediately convert toInstant
. Then proceed with your business logic. - Do most of your work in UTC. Tracking moments, debugging, logging, exchanging date-time values, and persisting to database should generally be done in UTC. Learn to forget about your own parochial time zone when on the job as a programmer. Keep a second clock on your desk set to UTC.
问题提到数据库工作.这是一个简短的摘要.搜索堆栈溢出以获取更多详细信息,因为已经处理了很多次.
The Question mentions database work. Here is a quick summary. Search Stack Overflow for more detail as this has been handled many times already.
从JDBC 4.2开始,我们可以直接与数据库交换 java.time 对象.使用
PreparedStatement::setObject
和ResultSet::getObject
.无需再次触摸可怕的java.sql.*
类,例如java.sql.Timestamp
.As of JDBC 4.2, we can directly exchange java.time objects with the database. Use
PreparedStatement::setObject
andResultSet::getObject
. No need to ever again touch the terriblejava.sql.*
classes such asjava.sql.Timestamp
.您 也许可以交换
Instant
,但是JDBC规范不要求这样做.规范反而要求OffsetDateTime
.You may be able to exchange an
Instant
but the JDBC spec does not require that. The spec instead requiresOffsetDateTime
.检索.
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
还有存储.
myPreparedStatement.setObject( … , odt ) ;
如果手边有
Instant
,请转换为ZoneOffset.UTC
.If you have an
Instant
in hand, convert toOffsetDateTime
using the constantZoneOffset.UTC
.OffsetDateTime odt = Instant.atOffset( ZoneOffset.UTC ) ;
要查看某个区域的挂钟时间,请应用
ZoneId
.To view that moment through the wall-clock time of some region, apply a
ZoneId
.ZoneId z = ZoneId.of( "Africa/Tunis" ) ; ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;
要将
ZonedDateTime
存储到数据库,请转换为OffsetDateTime
.这会剥夺时区信息(该地区人民根据政客的决定对过去,现在和将来进行的更改的历史记录),留下日期,时间和偏移量-from-UTC(小时数-分钟-秒数).To store a
ZonedDateTime
to the database, convert toOffsetDateTime
. This strips off the time zone information (the history of past, present, and future changes made to the offset used by the people of this region as decided by their politicians), leaving the date, the time-of-day, and the offset-from-UTC (a number of hours-minutes-seconds).OffsetDateTime odt = zdt.toOffsetDateTime();
大多数数据库在UTC中为SQL标准类型
TIMESTAMP WITH TIMESTAMP
的列存储时间.将OffsetDateTime
提交到数据库时,您的JDBC驱动程序可能会将OffsetDateTime
中的偏移量调整为零小时/分钟-秒(与UTC本身相对).但是我喜欢明确地这样做.它使调试更加容易,并且向读者展示了我对存储在UTC中的那一刻的理解.Most databases store a moment in UTC for a column of the SQL-standard type
TIMESTAMP WITH TIMESTAMP
. When submitting yourOffsetDateTime
to the database, your JDBC driver is likely to adjust the offset in theOffsetDateTime
to zero hours-minutes-seconds (to UTC itself). But I like do so explicitly. It makes debugging easier, and it demonstrates to the reader my understanding of the moment being stored in UTC.OffsetDateTime odt = zdt.toOffsetDateTime().withOffsetSameInstant( ZoneOffset.UTC ) ;
这篇关于java.util.Date和Zoneddatetime有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
Java带有两个非常不同的用于处理日期时间工作的框架:一组尴尬且失败的遗留类集,以及在
Java comes with two very different frameworks for handling date-time work: a terribly awkward and failed set of legacy classes, and an modern industry-leading set of classes found in the java.time package.
旧版➙现代: