问题
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.
Any help would be appreciated..
回答1:
tl;dr
Whats the difference between java.util.Date and Zoneddatetime?
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 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.
Legacy ➙ modern:
java.util.Date
was replaced byjava.time.Instant
- Both represent a moment in UTC.
java.util.GregorianCalendar
was replaced byjava.time.ZonedDateTime
- Both represent a moment as seen in a particular time zone.
java.util.Date
The Date
class represents a moment in UTC. That is, a date, a time-of-day, plus the context of UTC.
Internally, it is a count of milliseconds since the epoch reference date of first moment of 1970 in UTC, 1970-01-01T00:00:00Z.
To complicate matters:
- 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.
Confused? Yes, this class is confusing, a wretched mess of poor design decisions. Compounded by the later addition of java.util.Calendar
& GregorianCalendar
.
All of these troublesome date-time classes bundled with the earliest version of Java are now supplanted entirely by the java.time classes.
In particular, java.util.Date
is replaced by java.time.Instant
. Both represent a moment in UTC as count from the epoch of 1970 UTC. But Instant
carries a finer resolution, nanoseconds rather than milliseconds.
You can convert back-and-forth between the legacy class Date
and the modern class Instant
by calling new methods added to the old class. Usually, you will avoid ever using Date
. But when interfacing with old code not yet updated to java.time, you may need to convert.
java.time.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).
So Instant
and ZonedDateTime
are similar in that they both represent a moment, a specific point on that timeline. The difference is that ZonedDateTime
knows about the rules of a time zone. So a ZonedDateTime
knows how to account for anomalies such as Daylight Saving Time (DST) or other changes to time-keeping required by politicians.
You can think of it as:
ZonedDateTime
= (Instant
+ZoneId
)
We can easily adjust from UTC to some time zone by applying a time zone (ZoneId
) to a Instant
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).
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
zdt.toString(): 2019-02-28T04:32:43.366+09:00[Asia/Tokyo]
Crucial concept: Instant
and ZonedDateTime
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.
As for the legacy classes, the equivalent of ZonedDateTime
is GregorianCalendar, a concrete implementation of java.util.Calendar. Indeed, the old class GregorianCalendar
gained new methods for conversion to/from ZonedDateTime
.
ZonedDateTime zdt = myGregorianCalendar.toZonedDateTime(); // Convert from legacy to modern class.
…and…
GregorianCalendar gc = GregorianCalendar.from( zdt ) ; // Convert from modern to legacy class.
Conclusion
So a Date
is equivalent to a Instant
, both being a moment in UTC. But a ZonedDateTime
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.
Tips:
- 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.
Database
The Question mentions database work. Here is a quick summary. Search Stack Overflow for more detail as this has been handled many times already.
As of JDBC 4.2, we can directly exchange java.time objects with the database. Use PreparedStatement::setObject
and ResultSet::getObject
. No need to ever again touch the terrible java.sql.*
classes such as java.sql.Timestamp
.
You may be able to exchange an Instant
but the JDBC spec does not require that. The spec instead requires OffsetDateTime
.
Retrieval.
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
And storage.
myPreparedStatement.setObject( … , odt ) ;
If you have an Instant
in hand, convert to OffsetDateTime using the constant ZoneOffset.UTC.
OffsetDateTime odt = Instant.atOffset( ZoneOffset.UTC ) ;
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 ) ;
To store a ZonedDateTime
to the database, convert to OffsetDateTime
. 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();
Most databases store a moment in UTC for a column of the SQL-standard type TIMESTAMP WITH TIMESTAMP
. When submitting your OffsetDateTime
to the database, your JDBC driver is likely to adjust the offset in the OffsetDateTime
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 ) ;
回答2:
java.util.Date
is an almost deprecated class which provide a wrapper around millisecond value. It does not provide any information about the time zone, hasn't any helpful methods and you should always avoid using it.
ZonedDateTime
is a class from new JDK8
date API which provides a date-time with a time-zone in the ISO-8601 calendar system. You should check
Oracle's explanation for new date format
回答3:
Sixteen years ago, I wrote an article for JavaWorld magazine entitled What's Your Time Zone which dealt with the issue you describe when using class java.util.Date
. In order to "see" the value of an instance of class java.util.Date
, you have to convert it to a String
. Before java 1.8, this conversion always took the time zone into consideration as well. That's one of the reasons why, in Java 1.8, a new Date-Time API was introduced. New code that's written for Java versions 1.8 and above, should use the new API. I believe you should also consider converting old code to use the new API, if possible.
来源:https://stackoverflow.com/questions/54911481/whats-the-difference-between-java-util-date-and-zoneddatetime