На самом деле, Крис Лерчер ударил ногтем по голове, но он сделал это только в кратком комментарии, поэтому я хотел расширить его.
Вообразите двух секундомеров; один находится где-то, где UTC - это местное время 1 января 1970 года, а другой секундомер - локальный в вашем районе (скажем, он в Нью-Йорке, через 5 часов после UTC). В полночь UTC 1 января 1970 года запускается секундомер UTC. Через 5 часов ваш местный секундомер запущен. Эти два времени секундомера отличаются на некоторую величину, определяемую только тем, что разница между UTC была от вашего местного времени в по местному полуночи 1 января 1970 . Любые махинации, спасающие дневное время, с тех пор не имеют никакого отношения к разнице между этими секундомерами. Таким образом, любые поправки на летнее время для вашего настоящего времени или времени, когда вы конвертируете , не имеют значения. Все, что вам нужно, это то, сколько позже ваш местный секундомер запустился 1 января 1970 года .
Как указал Крис, это просто: getOffset (0L), поэтому:
int offset = TimeZone.getDefault().getOffset(0L);
long newTime = oldTime - offset;
... должно работать нормально. Однако ....
Чтобы действительно понять это, обратите внимание: «0L» в getOffset () - это миллисекунды с эпохи UTC (которая является единственной действительной эпохой). Итак, ваша переменная смещения будет иметь количество секунд смещения в полночь UTC (то есть, когда это было, скажем, 19:00 31.12.1969 г. в Нью-Йорке). Если ваше местное время было переключено на / с перехода на летнее время в эти последние часы до местного полуночи, то getOffset (0L) не будет корректным. Вы должны знать, каков был ваш статус перехода на летнее время в местный полночь, а не в полночь UTC.
Я был бы удивлен, если бы это было так, где угодно (то есть, любой часовой пояс, который изменился на / из летнего времени между их местной полуночью и полуночью UTC 1 января 1970 года). Однако, просто для удовольствия, дешевый хак, который поможет избежать этого, будет проверять, изменилось ли смещение в эти часы:
// 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 будет тем, что было смещением часового пояса через миллисекунды с временным смещением после полуночи UTC в 1970 году. Если не произошло изменения летнего времени, localMidnightOffset сравняет смещение, и все готово. Если какое-то изменение DST действительно произошло, то вам, возможно, придется охотиться ... вероятно, продолжайте делать
localMidnightOffset = TimeZone.getDefault().getOffset(-localMidnightOffset)
пока он не перестанет меняться ... и надеюсь, что вы не попадете в бесконечный цикл. Мне любопытно посмотреть, есть ли у кого-нибудь решение с гарантированной конвергенцией.
Что-то заставляет тебя желать, чтобы мир был плоским, а?