我一直在使用旧版Date API以yyyyMMdd'T'HHmmss
格式计算两次之间的时间差。
客户端在请求中设置requestExpirationTime
属性,并且服务器进行了验证检查,以确保“ RequestExpirationTime不在当前系统时间之前”。
客户:
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd'T'HHmmss");
Timestamp originatingTimestamp = new Timestamp(new Date().getTime());
// duration is offset 5minutes for exmaple
Timestamp requestExpirationTimestamp = new Timestamp(originatingTimestamp.getTime() + duration);
request.setRequestExpirationTimestamp(simpleDateFormat.format(requestExpirationTimestamp));
服务器:
try {
Date systemTime = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd'T'HHmmss");
String ret = request.getRequestExpirationTimestamp();
if (ret != null) {
Date requestExpirationTimestamp = sdf.parse(ret);
if (requestExpirationTimestamp.before(systemTime)) {
logger.info("Request timedout: RequestExpirationTime is before current system time");
}
}
}
由于服务器上的systemTime
出现在IST(印度标准时间)中,并且客户端可以发送任何UTC / IST,因此此代码出现了问题。
我现在已移至Java 8,因此可以将旧的Date Api保留在Java中。
如何确保此类时区问题不会出现在我的代码中?我尝试将timeZone设置为服务器上的SimpleDateFormat,但new Date()
在不同服务器上的行为不同。
感谢您的帮助。
客户
确保您始终以UTC发送时间:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuuMMdd'T'HHmmss");
String requestExpirationTime = OffsetDateTime.now(ZoneOffset.UTC)
.plusMinutes(5)
.format(formatter);
System.out.println(requestExpirationTime);
立即运行的示例输出:
20200506T183409
服务器
现在服务器知道时间是UTC。我假设它使用的格式化程序与客户端使用的格式化程序相同。
OffsetDateTime dateTime = LocalDateTime.parse(requestExpirationTime, formatter)
.atOffset(ZoneOffset.UTC);
OffsetDateTime systemTime = OffsetDateTime.now(ZoneOffset.UTC);
if (dateTime.isBefore(systemTime)) {
System.out.println("Request timedout: RequestExpirationTime is before current system time");
} else {
System.out.println("OK");
}
确定
Tip
您可以将Z
附加到您的时间戳字符串,以使其明确表示它是UTC。这样可以避免以后出现一些错误。
20200506T183409Z