上下左右搜索 - 找不到这个问题的简单答案:
我有java.util.Date实例,它从mySQL获取它的值。
我也有登录用户的时区代码。
我需要在用户时区获取实际时间。
例如:
我的服务器 - 机器时区是GMT + 2。
我在DB中的日期值是:2017-02-09 16:38:58.000
根据我的服务器机器时区我把它变成了日期实例:2017-02-09T16:38:58.000 + 0200
现在我需要知道如果做什么:
如果是示例,我的客户端时区代码是GMT + 4,我想得到:
2017-02-09 20:38:58.000
纯日期,这是我的时区,不包含“+4”或“GMT”指示。
简而言之:将我的java.util.date转换为特定时区的纯日期。
听起来很简单?在阅读了很多文档后,我已经不确定这是非常简单的。
java.util.Date不存储任何时区。它只存储自'epoch'以来的毫秒数,即1970年1月1日00:00:00 UTC。
因此,您所要做的就是了解服务器计算机的时区,找到此时区与您要将其转换为时区的时间段,并添加或减去句点。
更新:
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);
附:是的,您必须手动操作时区,如上所述,java.util.Date
不存储此信息(假设每个日期都是UTC)。
据我所知,您的数据库中的日期时间是UTC,但是当您检索它时,您(错误地)收到2017-02-09T16:38:58.000 + 02:00。
首先,如果可以,将MySQL数据库列的数据类型更改为timestamp
(在其他一些数据库中,它将被称为timestamp with time zone
)。这将确保MySQL知道时间是UTC,并且应该使您能够在正确的时间点检索它们,而不是在错误的时区中正确的时间。这反过来将为您提供转换到客户端时区的最佳起点。
其次,从java.time(现代Java日期和时间API)中将您的值检索为适当的类型。避免使用java.util.Date
,因为它的设计很差,无法处理不同的时区。例如,如果您的数据库数据类型是datetime
:
LocalDateTime dateTime = yourResultSet.getObject("your_col", LocalDateTime.class);
LocalDateTime
是一个没有时区的日期和时间,所以你不能得到错误的时区。提供您知道的偏移量:
OffsetDateTime odt = dateTime.atOffset(ZoneOffset.UTC);
转换为客户端时区:
ZoneId clientTimeZone = ZoneId.of("Indian/Reunion");
ZonedDateTime clientDateTime = odt.atZoneSameInstant(clientTimeZone);
System.out.println(clientDateTime);
2017-02-09T20:38:58 + 04:00 [印度/留尼汪]
让自己喜欢使用区域/城市格式的实时区域,而不是像+04:00
这样的偏移量。它更容易理解,更具有前瞻性。 Indian / Reunion只是一个例子,当然,为您的客户使用正确的一个。
上面的ZonedDateTime
有偏移量和时区。建议保持这种方式,我不认为它有任何伤害。客户端始终可以选择不显示它。如果您仍然坚持,请再次转换为LocalDateTime
:
LocalDateTime clientDateTimeWithoutOffset = clientDateTime.toLocalDateTime();
System.out.println(clientDateTimeWithoutOffset);
2017-02-09T20:38:58
如果数据库数据类型是timestamp
:
OffsetDateTime odt = yourResultSet.getObject("your_col", OffsetDateTime.class);
这节省了上面的第一步。其余部分是相同的。
Oracle tutorial: Date Time解释如何使用java.time。