我正在传递一个哈希表,其中包含日期为
2019-03-08 00:00:00.0
到servlet并在servlet端读取哈希图时,我得到的日期为
2019-03-07 23:00:00.0
它只能在夏令时转换一小时。如何在Java中处理此问题?
java.util.Date d = new java.util.Date();
d.setDate(06);
d.setMonth(02);
d.setYear(2018);
d.setHours(23);
d.setMinutes(59);
d.setSeconds(00);
ObjectInputStream is = new ObjectInputStream(request.getInputStream());
java.util.Date obj=(java.util.Date)is.readObject();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(response.getOutputStream());
Vector vector = new Vector();
vector.add(d);
objectOutputStream.writeObject(vector);
objectOutputStream.flush();
objectOutputStream.close();
从Java类中读取时,Iam减少了一个小时。
答案 0 :(得分:0)
如果服务器时区设置未考虑夏令时(DST),可能会发生这种情况。例如,我以美国/亚松森时区为例。亚松森是巴拉圭最大的城市和首都。巴拉圭在标准时间的偏移量为-04:00,但在夏季的偏移量为-03:00。夏季时间仍在3月8日生效,直到3月24日。
首先演示出了什么问题:
System.setProperty("user.timezone", ZoneId.ofOffset("GMT", ZoneOffset.ofHours(-4)).getId());
// Send a timestamp from America/Asuncion time zone
ZoneId zone = ZoneId.of("America/Asuncion");
// Create the timestamp as March 8 at 00:00:00
Instant testTime
= ZonedDateTime.of(2019, 3, 8, 0, 0, 0, 0, zone).toInstant();
Timestamp ts = Timestamp.from(testTime);
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(baos)) {
objectOutputStream.writeObject(ts);
}
byte[] ba = baos.toByteArray();
try (ObjectInputStream is = new ObjectInputStream(new ByteArrayInputStream(ba))) {
java.util.Date obj = (java.util.Date) is.readObject();
System.out.println(obj);
}
}
对于这个简单的演示,我们不需要单独的客户端和服务器代码。我创建了一个Timestamp
对象,该对象在相关时区中具有已知的日期和时间,将其写入ObjectOutputStream
并使用相同的基础字节从ObjectInputStream
读回。我得到的是一个Timestamp
,表示同一时间点。为了演示接收器打印时会发生什么,我将默认时区设置在顶部。我正在使用-04:00
的恒定偏移量来演示在服务器时区未考虑夏令时的情况。它打印:
2019-03-07 23:00:00.0
所以您得到了相同的结果。这是因为-令人困惑-Timestamp.toString
使用JVM的时区设置来生成字符串。
如何解决?
当我们知道Timestamp
是从America / Asuncion时区发送的时,我们可以在服务器上显式使用该时区:
java.util.Date obj = (java.util.Date) is.readObject();
ZonedDateTime timeAsSent = obj.toInstant().atZone(zone);
System.out.println(timeAsSent);
2019-03-08T00:00-03:00 [美国/亚松森]
现在时间与最初写入对象输出流的时间一致。
更好的解决方法
如果可以的话,请完全避免使用旧类Date
和Timestamp
。这些课程的设计不佳,会在您身上耍花样。他们也早已过时。而是在客户端将ZonedDateTime
或Instant
写入对象流,当然在服务器端读取相同的类型。这样便不会有惊喜的地方。