实际上,Chris Lercher 一针见血,但他只发表了简短的评论,所以我想对此进行扩展。
想象两个秒表;一个是 UTC 是 1970 年 1 月 1 日当地时间的地方,另一个秒表是您所在地区的本地时间(假设它在纽约,UTC 5 小时后)。在 1970 年 1 月 1 日 UTC 午夜,UTC 秒表启动。 5 小时后,您的本地秒表启动。这两个秒表时间存在一定差异,仅由 1970 年 1 月 1 日 当地时间午夜的 UTC 与您的当地时间之间的差异来确定。从那时起,任何夏令时的恶作剧都与这些秒表之间的差异无关。因此,对于您当前时间或您正在转换时间的任何 DST 更正都是无关紧要的。 您所需要的只是本地秒表在 1970 年 1 月 1 日开始的时间。
正如 Chris 指出的,这只是:getOffset(0L),所以:
int offset = TimeZone.getDefault().getOffset(0L);
long newTime = oldTime - offset;
... 应该可以正常工作。 然而....
为了帮助真正掌握这一点,请注意:getOffset() 中的“0L”是自 UTC 纪元(这是唯一的 real 纪元)以来的毫秒数。因此,您的偏移变量将具有 UTC 午夜偏移的秒数(例如,1969 年 12 月 31 日纽约的 19:00)。如果您的当地时间在local 午夜之前的最后几个小时内切换为夏令时,则 getOffset(0L) 将不正确。您需要知道 local 午夜的夏令时状态,而不是 UTC 的午夜。
如果在任何地方(即,在 1970 年 1 月 1 日当地时间午夜和 UTC 午夜之间更改为/从 DST 更改的任何时区)都是这种情况,我会感到惊讶。然而,只是为了好玩,一个廉价的黑客来帮助防止这种情况是检查偏移量是否在这些小时内发生了变化:
// Offset at UTC midnight
int offset = TimeZone.getDefault().getOffset(0L);
long newTime = oldTime - offset;
// Offset at Local midnight
int localMidnightOffset = TimeZone.getDefault().getOffset(-offset);
在这里,localMidnightOffset 将是 1970 年 UTC 午夜之后 time-offset 毫秒的时区偏移量。如果没有发生 DST 更改,则 localMidnightOffset 将等于偏移量,您就完成了。如果某些 DST 更改确实发生了,那么您可能不得不四处寻找......可能继续做一个
localMidnightOffset = TimeZone.getDefault().getOffset(-localMidnightOffset)
直到它停止变化……并希望你不要陷入死循环。我很想知道是否有人有保证收敛的解决方案。
有点让你希望世界是平的,对吧?