I have some TimeStamp
and I have date format "EEEE, MMM dd, yyyy hh:mm a zzz"
. But I don't know how I can show this timestamp with timezone. When I trying to show it I get wrong DateTime or wrong timezone
example1:
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date(device.getUpdatedDate().getTime())); // here is 2018-07-09 20:02:26.506000
SimpleDateFormat sdf = new SimpleDateFormat(EMAIL_DATE_FORMAT);
sdf.format(calendar.getTime()); // i have wrong timezone
and i get Monday, Jul 09, 2018 08:02 PM EEST
but when i add sdf.setTimeZone(TimeZone.getTimeZone("HST"));
i have right timezone and wrong time
Monday, Jul 09, 2018 07:02 AM HST
expected result Monday, Jul 09, 2018 08:02 PM HST
actual results: Monday, Jul 09, 2018 08:02 PM EEST
or Monday, Jul 09, 2018 07:02 AM HST
As I understand
device.getUpdatedDate()
returns ajava.sql.Timestamp
, for example2018-07-09 20:02:26.506000
. I assume that (contrary to the idea of a timestamp) this date and time was produced without time zone, but that you know that it is in Pacific/Honolulu time zone (Hawaii Standard Time or HST, used in Hawaii all year).If you are getting the
Timestamp
from an SQL database (as would be normal) — don’t. TheTimestamnp
class is long outdated and quite confusing. Assuming you are using at least Java 8 and at least JDBC 4.2, you may get an instance of the modernLocalDateTime
from the database instead. Assuming thatrs
is your result set and your column is namedupdated_date
(I trust you to tailor the code to your situation):If your timestamp is stored in the database with time zone information you can do even better by using
Instant.class
instead and be sure to get the same point in time as in the database. The exact possibilities depend on the capabilities of your JDBC driver.In case you cannot avoid getting the
Timestamp
, convert it like this:With your example
Timestamp
and the formatter from my first code snippet above this prints:(assuming that
EMAIL_DATE_FORMAT
is defined as"EEEE, MMM dd, yyyy hh:mm a zzz"
).What went wrong in your code?
One confusing thing about
Timestamp
is that it represents a point in time (without time zone) but has often been used for representing a date and time of day (also without time zone) instead. So yourTimestamp
of 2018-07-09 20:02:26.506000 really holds the value (point in time) equal to 2018-07-09 20:02:26.506000 Eastern European Summer Time (EEST, as used in Украина/Ukraine) but is confusingly used bydevice.getUpdatedDate()
to mean 2018-07-09 20:02:26.506000 in Hawaii. NeitherDate
norSimpleDateFormat
change the point in time, which is why they give youMonday, Jul 09, 2018 08:02 PM EEST
or the equivalentMonday, Jul 09, 2018 07:02 AM HST
.Links:
Timestamp
in my answer to this question: Java - Convert java.time.Instant to java.sql.Timestamp without Zone offsetjava.time
.tl;dr
Same moment: Call
withZoneSameInstant
You adjusted from one time zone 3 hours ahead of UTC to another zone 10 hours behind UTC, for a total difference of 13 hours. Understand that 8 PM in one place is simultaneously 7 AM in the other.
Note our call to
withZoneSameInstant
(‘Instant’) in the following code.Different moment: Call
withZoneSameLocal
Apparently you wanted a different moment, a different point on the timeline, that has the same date and same time-of-day but a different time zone.
Note our call to
withZoneSameLocal
(‘Local’, not ‘Instant’) in the following code.Details
Real time zone
HST
&EEST
are pseudo-zones, not real time zones. Avoid these 3-4 letter codes as they are not standardized and are not even unique(!).Use real time zone names as defined in tzdata by the IANA. See a list in Wikipedia (possibly outdated). These names are in
Continent/Region
format such asAmerica/Montreal
orEurope/Tallinn
.Avoid legacy date-time classes
Avoid the terribly troublesome classes
Calendar
&SimpleDateFormat
. These were supplanted years ago by the java.time classes. Working with java.time is much clearer and easier.Let's get your starting point. I am guessing that by
EEST
you had in mind one of the eastern European time zones. I am choosing one arbitrarily.Generate a
String
representing the value of thatZonedDateTime
object. By default, use standard ISO 8601 format wisely extended to append the name of the time zone in square brackets.By
HST
I guess you mean Hawaii time. The proper name for that zone isPacific/Honolulu
.Let's adjust our Athens moment into this other zone for Hawaii. Same moment, same point on the timeline, but a different wall-clock time. Imagine a pair of friends in each place calling each and simultaneously looking up at a clock on their wall. Each sees a different time-of-day and possibly a different date, nevertheless they experience the same simultaneous moment, same point on the timeline.
On that date, Honolulu is ten hours behind UTC while Athens is three hours ahead. That is a total delta of thirteen hours. So, 8 PM (20:00) minus 13 is 7 AM. We expect to see 7 AM in Hawaii. Let's verify, by generating another string in ISO 8601 format.
Sure enough, 7 AM.
Perhaps what you wanted was the same date and same time-of-day located in Hawaii. This would mean you are not representing the same simultaneous moment. You would be representing a different point on the timeline, off by several hours.
The
ZonedDateTime
does provide for this function. CallZonedDateTime::withZoneSameLocal
meaning conceptually: Use the same internalLocalDate
and the same internalLocalTime
, but use a different assignedZoneId
.UTC
All this flipping around between time zones can drive a person batty. Get grounded by focusing on UTC. Think of UTC as The One True Time, and all other zones are but mere variations.
To adjust from a time zone to UTC, extract a
Instant
object from ourZonedDateTime
objects. AnInstant
is always in UTC by definition.The
Z
on the end means UTC, is pronounced Zulu, and is defined by ISO 8601 and other standards.About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as
java.util.Date
,Calendar
, &SimpleDateFormat
.The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for
java.sql.*
classes.Where to obtain the java.time classes?
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as
Interval
,YearWeek
,YearQuarter
, and more.