问题
Searching up and down, right and left - don't find simple answer to this question:
I have java.util.Date instance, which get its value from mySQL.
Also I have time-zone code of the logged-in user.
I need to get the actual time at user time-zone.
For example:
My server-machine time-zone is GMT+2.
My date value in DB is: 2017-02-09 16:38:58.000
According to my server-machine-time-zone I get it into date instance as: 2017-02-09T16:38:58.000+0200
Now I need to know what to do if:
In case, for sample, my client-time-zone-code is GMT+4, I want to get:
2017-02-09 20:38:58.000
Pure date, that is right to my time zone and not contain "+4" or "GMT" indication.
In short words: convert my java.util.date to pure date that right to specific time-zone.
Sound very simple? after read very much documentaion, I already not sure that this is really simple.
回答1:
java.util.Date does not store any time zone. It just stores the number of milliseconds since the 'epoch', which is 1 January 1970, 00:00:00 UTC.
Thus, all you have to do is to know the time zone of your server machine, find the period between this time zone and the time zone you want to convert it to and add or subtract the period.
UPDATE:
int clientGMT = 4; //GMT you want to convert to
int serverGMT = 2; //server's GMT
int delta = clientGMT - serverGMT; //delta between the dates
//assume this is the date in GMT + 2 received from the server
Date d1 = new SimpleDateFormat("dd.MM.yyyy hh:mm:ss").parse("12.03.2019 13:00:00");
//... and you want to convert it to GMT + 4 (client side's time zone)
Date resultDate = new Date(d1.getTime() + delta * 3600000);
P.S. Yes, you have to manipulate time zones manually, as I said above, java.util.Date
does not store this information (each date is assumed to be in UTC).
回答2:
Timestamp (with time zone)
As far as I have understood, the date-time in your database in UTC, but when you retrieve it, you (incorrectly) receive 2017-02-09T16:38:58.000+02:00.
First, if you can, change the datatype of your MySQL database column to timestamp
(in some other databases it would be called timestamp with time zone
). This will make sure that MySQL knows that the times are in UTC and should enable you to retrieve them as the right point in time rather than the right time of day in the wrong time zone. This in turn will give you the best starting point for converting to the client time zone.
java.time
Second, retrieve your value into an appropriate type from java.time, the modern Java date and time API. Avoid java.util.Date
since it is poorly designed and cannot handle different time zones. For example, if your database datatype is datetime
:
LocalDateTime dateTime = yourResultSet.getObject("your_col", LocalDateTime.class);
LocalDateTime
is a date and time of day without time zone, so you cannot get the wrong time zone. Supply the offset that you know is right:
OffsetDateTime odt = dateTime.atOffset(ZoneOffset.UTC);
Convert to client time zone:
ZoneId clientTimeZone = ZoneId.of("Indian/Reunion");
ZonedDateTime clientDateTime = odt.atZoneSameInstant(clientTimeZone);
System.out.println(clientDateTime);
2017-02-09T20:38:58+04:00[Indian/Reunion]
Do yourself the favour of using a real time zone in the region/city format rather than an offset like +04:00
. It’s easier to understand and more future-proof. Indian/Reunion is just an example, of course, use the correct one for your client.
The ZonedDateTime
above has both offset and time zone in it. It’s recommended to keep it that way, and I don’t see it doing any harm. The client can always opt not to display it. If you still insist, convert to LocalDateTime
again:
LocalDateTime clientDateTimeWithoutOffset = clientDateTime.toLocalDateTime();
System.out.println(clientDateTimeWithoutOffset);
2017-02-09T20:38:58
If the database datatype is timestamp
:
OffsetDateTime odt = yourResultSet.getObject("your_col", OffsetDateTime.class);
This saves the first step above. The remainder is the same.
Link
Oracle tutorial: Date Time explaining how to use java.time.
来源:https://stackoverflow.com/questions/55117212/java-util-date-get-the-actual-date-at-client-timezone