简体   繁体   English

Java.util.date获取客户端时区的实际日期

[英]Java.util.date get the actual date at client timezone

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. 我有java.util.Date实例,该实例从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. 我的服务器计算机时区为GMT + 2。

My date value in DB is: 2017-02-09 16:38:58.000 我在DB中的日期值为: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 根据我的服务器机器时区,我将其放入日期实例为: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: 举例来说,如果我的客户时区代码是GMT + 4,我想得到:

2017-02-09 20:38:58.000 2017-02-09 20:38:58.000

Pure date, that is right to my time zone and not contain "+4" or "GMT" indication. 纯日期,即我所在的时区,不包含“ +4”或“ GMT”指示。

In short words: convert my java.util.date to pure date that right to specific time-zone. 简而言之:将我的java.util.date转换为对特定时区的纯日期。

Sound very simple? 听起来很简单? after read very much documentaion, I already not sure that this is really simple. 在阅读了很多文献之后,我已经不确定这是否真的很简单。

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. 据我了解,UTC数据库中的日期时间,但是在检索它时,您(错误地)收到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 ). 首先,如果可以的话,将MySQL数据库列的数据类型更改为timestamp (在其他一些数据库中,它称为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. 这样可以确保MySQL知道时间是UTC,并且应该使您能够将它们作为正确的时间点而不是在错误的时区中的正确时间进行检索。 This in turn will give you the best starting point for converting to the client time zone. 这将为您提供转换到客户端时区的最佳起点。

java.time java.time

Second, retrieve your value into an appropriate type from java.time, the modern Java date and time API. 其次,从现代Java日期和时间API java.time中将您的值检索为适当的类型。 Avoid java.util.Date since it is poorly designed and cannot handle different time zones. 避免使用java.util.Date因为它的设计不正确并且无法处理不同的时区。 For example, if your database datatype is datetime : 例如,如果您的数据库数据类型为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. LocalDateTime是没有时区的日期和时间,因此您无法获取错误的时区。 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] 2017-02-09T20:38:58 + 04:00 [印度/留尼汪]

Do yourself the favour of using a real time zone in the region/city format rather than an offset like +04:00 . 请自己使用区域/城市格式的实时区域,而不要使用+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. 上面的ZonedDateTime在其中具有偏移量和时区。 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

    LocalDateTime clientDateTimeWithoutOffset = clientDateTime.toLocalDateTime();
    System.out.println(clientDateTimeWithoutOffset);

2017-02-09T20:38:58 2017-02-09T20:38:58

If the database datatype is timestamp : 如果数据库数据类型为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. Oracle教程:Date Time说明如何使用java.time。

java.util.Date does not store any time zone. java.util.Date不存储任何时区。 It just stores the number of milliseconds since the 'epoch', which is 1 January 1970, 00:00:00 UTC. 它仅存储自“纪元”(即1970年1月1日,UTC时间00:00:00)以来的毫秒数。

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);

PS 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). PS:是的,您必须手动操作时区,正如我上面所说, java.util.Date不存储此信息(每个日期均假定为UTC)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM