问题描述
我有一个特殊的要求,我必须获取系统时区与任何其他远程时区之间的差,然后如果系统时区是远程时区的AHEAD,则将当前时间添加到该日期,如果是BEHIND,则将其减去。 / p>
还需要考虑夏令时(DST),因为可以在任何时区中部署该代码。
我尝试了以下方法,
long Now = System.currentTimeMillis();
long diffGMT = TimeZone.getTimeZone(ZoneId.systemDefault()).getoffset(Now) -
TimeZone.getTimeZone("GMT").getoffset(Now);
long diffAEST = TimeZone.getTimeZone(ZoneId.systemDefault()).getoffset(Now) -
TimeZone.getTimeZone("AEST").getoffset(Now);
System.out.println("diffGMT = " + diffGMT);
System.out.println("diffAEST = " + diffAEST);
但是返回的两个值都是正值。
我的系统时间是IST,我尝试了GMT,即BEHIND和AEST(澳大利亚),即AHEAD。
我在这里做错了吗?
一旦我得到所需的正或负时间,那么我就可以按照以下代码加或减小时,
long totalSecs = (calculatedValueInMillis)/1000;
long hours = (totalSecs / 3600);
long mins = (totalSecs / 60) % 60;
long secs = totalSecs % 60;
解决方法
问题是TimeZone.getTimeZone(String ID)
“如果无法理解给定的ID,则返回GMT区域”。它不会引发异常。
由于没有名为AEST
的时区,因此TimeZone.getTimeZone("AEST")
会解析为GMT
。
解决方案:改用Australia/Sydney
。
问题中的代码是混合时间API:TimeZone.getTimeZone(ZoneId.systemDefault())
由于其余代码使用的是旧的Date API,因此它应该只使用了TimeZone.getDefault()
。
或者,它可以使用更新的Time API,例如像这样:
Instant now = Instant.now();
System.out.println(Date.from(now)); // Show default time zone
int offsetLocal = ZoneId.systemDefault().getRules().getOffset(now).getTotalSeconds();
int offsetSydney = ZoneId.of("Australia/Sydney").getRules().getOffset(now).getTotalSeconds();
int offsetGMT = 0; // aka ZoneOffset.UTC.getTotalSeconds()
// // aka ZoneId.of("GMT").getRules().getOffset(now).getTotalSeconds()
long diffGMT = offsetLocal - offsetGMT;
long diffAEST = offsetLocal - offsetSydney;
System.out.println("diffGMT = " + diffGMT);
System.out.println("diffAEST = " + diffAEST);
long hours = (diffAEST / 3600);
long mins = (diffAEST / 60) % 60;
long secs = diffAEST % 60;
System.out.printf("diffAEST = %02d:%02d:%02d%n",hours,Math.abs(mins),Math.abs(secs));
要测试以系统时间IST运行,请首先添加以下行:
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Kolkata"));
输出
Tue Sep 15 19:44:36 IST 2020
diffGMT = 19800
diffAEST = -16200
diffAEST = -4:30:00