En realidad, Chris Lercher dio en el clavo en la cabeza, pero él sólo lo hizo en un breve comentario, así que quería expandir en él.
Imagine dos cronómetros; uno está en algún lugar donde UTC es la hora local el 1 de enero de 1970, y el otro cronómetro es local para su área (digamos que está en Nueva York, 5 horas después de UTC). En UTC medianoche, el 1 de enero de 1970, se inicia el cronómetro UTC. 5 horas después, se inicia su cronómetro local. Esos dos tiempos de cronómetro difieren en cierta cantidad, determinado solo por cuál fue la diferencia entre UTC de su hora local en medianoche local el 1 de enero de 1970. Cualquier travesura que ahorre luz del día, desde entonces, no tiene relación con la diferencia entre esos cronómetros. Por lo tanto, cualquier corrección DST para su presente tiempo o para las veces que está convirtiendo, son irrelevantes.Todo lo que necesita es cuánto más tarde comenzó su cronómetro local el 1 de enero de 1970.
Como Chris señaló, esto es sólo: getOffset (0L), por lo que:
int offset = TimeZone.getDefault().getOffset(0L);
long newTime = oldTime - offset;
... debería funcionar bien. Sin embargo ....
Para ayudar realmente a comprender esto, tenga en cuenta lo siguiente: que "0L" en getOffset() son los milisegundos desde el tiempo UTC (que es la única verdadera época). Por lo tanto, su variable de compensación tendrá el número de segundos de compensación a la medianoche UTC (es decir, cuando fue, por ejemplo, 19:00 el 31/12/1969 en Nueva York). Si su hora local cambia a/de horario de verano en las últimas horas antes de local medianoche, getOffset (0L) no sería correcto. Debe saber cuál fue su estado de ahorro de luz diurna al local medianoche, no la medianoche de UTC.
Me sorprendería que este fuera el caso, en cualquier lugar (es decir, cualquier zona horaria que cambiara a/desde el horario de verano entre su medianoche local y la medianoche UTC del 1 de enero de 1970). Sin embargo, sólo por diversión, un truco barato para ayudar a protegerse contra esto sería para comprobar si el desplazamiento cambiado en esas horas:
// Offset at UTC midnight
int offset = TimeZone.getDefault().getOffset(0L);
long newTime = oldTime - offset;
// Offset at Local midnight
int localMidnightOffset = TimeZone.getDefault().getOffset(-offset);
Aquí, localMidnightOffset será lo que el desplazamiento de zona horaria era a la vez -offset milisegundos después UTC medianoche en 1970. Si no se produjo ningún cambio en el horario de verano, entonces localMidnightOffset igualará el desplazamiento y listo. Si algún cambio DST hizo produce, entonces es posible que tenga que buscar alrededor ... probablemente lo siga haciendo un
localMidnightOffset = TimeZone.getDefault().getOffset(-localMidnightOffset)
hasta que se detenga el cambio ... y espero que no queden atrapados en un bucle sin fin. Tengo curiosidad por ver si alguien tiene una solución convergente garantizada.
Un poco te hace desear que el mundo fuera plano, ¿eh?
Esto no cuenta para DST en absoluto. –
@Quartz - no tiene porque, ya que estamos lidiando con deltas de la Época. ¿Tiene un ejemplo (zone and timeSinceLocalEpoch) donde esto falla? – leedm777