我正在尝试处理时间,而我偶然发现了Java中有些令我感到困惑的东西。采取以下示例代码:
public static void main(String[] args)
{
//Calendar set to 12:00 AM of the current day (Eastern Daylight Time)
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT-4"));
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
/////
//Calendar set to 12:00 AM of the current day (UTC time)
Calendar utcCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
utcCal.set(Calendar.HOUR_OF_DAY, 0);
utcCal.set(Calendar.MINUTE, 0);
utcCal.set(Calendar.SECOND, 0);
utcCal.set(Calendar.MILLISECOND, 0);
/////
long oneHourMilliseconds = 3600000;
System.out.println((cal.getTimeInMillis() - utcCal.getTimeInMillis()) / oneHourMilliseconds);
}
我以2种形式之一可视化用于计算
cal
表示的时间的算法:Epoch - 4 * oneHourMilliseconds
)的毫秒数。 这两种算法所产生的结果都比
utcCal
落后4小时,但是运行代码会返回4
。有人可以向我解释为什么
cal
尽管设置为比utcCal
落后4个小时的时区,却在utcCal的4个小时后仍然具有毫秒值?该代码不应该返回-4
吗? 最佳答案
这是一段不幸的历史。 ID为“GMT-4”的时区就是您期望的“UTC + 4”,即比UTC早4小时。
从tzdb的etcetera文件中:
# We use POSIX-style signs in the Zone names and the output abbreviations,
# even though this is the opposite of what many people expect.
# POSIX has positive signs west of Greenwich, but many people expect
# positive signs east of Greenwich. For example, TZ='Etc/GMT+4' uses
# the abbreviation "GMT+4" and corresponds to 4 hours behind UTC
# (i.e. west of Greenwich) even though many people would expect it to
# mean 4 hours ahead of UTC (i.e. east of Greenwich).
从this similar explanation: