[java] ¿Por qué restar estas dos veces (en 1927) da un resultado extraño?


Answers

Has encontrado una discontinuidad horaria local :

Cuando el horario estándar local estaba a punto de llegar el domingo 1 de enero de 1928, 00:00:00 los relojes retrocedieron 0:05:52 horas hasta el sábado 31 de diciembre de 1927, a las 23:54:08 hora local estándar.

Esto no es particularmente extraño y ha sucedido prácticamente en todas partes en un momento u otro ya que las zonas horarias se cambiaron o cambiaron debido a acciones políticas o administrativas.

Question

Si ejecuto el siguiente programa, que analiza dos cadenas de fechas haciendo referencia a las horas de diferencia de 1 segundo y las compara:

public static void main(String[] args) throws ParseException {
    SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
    String str3 = "1927-12-31 23:54:07";  
    String str4 = "1927-12-31 23:54:08";  
    Date sDt3 = sf.parse(str3);  
    Date sDt4 = sf.parse(str4);  
    long ld3 = sDt3.getTime() /1000;  
    long ld4 = sDt4.getTime() /1000;
    System.out.println(ld4-ld3);
}

El resultado es:

353

¿Por qué ld4-ld3 no es 1 (como esperaría de la diferencia de un segundo en los tiempos), sino 353 ?

Si cambio las fechas a veces 1 segundo después:

String str3 = "1927-12-31 23:54:08";  
String str4 = "1927-12-31 23:54:09";  

Entonces ld4-ld3 será 1 .

Versión de Java:

java version "1.6.0_22"
Java(TM) SE Runtime Environment (build 1.6.0_22-b04)
Dynamic Code Evolution Client VM (build 0.2-b02-internal, 19.0-b04-internal, mixed mode)

Timezone(`TimeZone.getDefault()`):

sun.util.calendar.ZoneInfo[id="Asia/Shanghai",
offset=28800000,dstSavings=0,
useDaylight=false,
transitions=19,
lastRule=null]

Locale(Locale.getDefault()): zh_CN



En mi humilde opinión, la localización omnipresente e implícita en Java es su mayor defecto de diseño. Puede estar destinado a interfaces de usuario, pero, francamente, quién realmente usa Java para las interfaces de usuario de hoy excepto por algunos IDEs donde básicamente se puede ignorar la localización porque los programadores no son exactamente el público objetivo para ello. Puede solucionarlo (especialmente en servidores Linux) de la siguiente manera:

  • exportar LC_ALL = C TZ = UTC
  • configura el reloj de tu sistema en UTC
  • nunca utilice implementaciones localizadas a menos que sea absolutamente necesario (es decir, solo para visualización)

A los miembros de Java Community Process les recomiendo:

  • hacer que los métodos localizados no sean los predeterminados, pero requieren que el usuario solicite explícitamente la localización.
  • use UTF-8 / UTC como el valor predeterminado fijo en su lugar porque es simplemente el valor predeterminado hoy. No hay ninguna razón para hacer otra cosa, excepto si desea producir hilos como este.

Quiero decir, vamos, ¿las variables estáticas globales no son un patrón anti-OO? Nada más son esos incumplimientos omnipresentes dados por algunas variables de entorno rudimentarias .......




Al incrementar el tiempo, debe volver a convertir a UTC y luego sumar o restar. Use la hora local solo para mostrar.

De esta manera podrá caminar por cualquier período donde las horas o los minutos suceden dos veces.

Si convirtió a UTC, agregue cada segundo y convierta a la hora local para mostrar. Pasarías a las 11:54:08 p.m. LMT - 11:59:59 p.m. LMT y luego a las 11:54:08 p.m. CST - 11:59:59 p.m. CST.




Lamento decir eso, pero la discontinuidad de tiempo se ha movido un poco

JDK 6 hace dos años, y en JDK 7 recientemente en la actualización 25 .

Lección para aprender: evite los tiempos no UTC a toda costa, excepto, tal vez, para mostrarlos.




Related