2009-08-06 10 views
18

Aparece el siguiente código para demostrar un error en java.util.Date donde se agrega una hora si el reloj local está configurado en GMT con el ajuste de horario de verano activado y la hora es anterior al 1 de noviembre de 1971. Mi primera suposición es siempre que lo he entendido mal ¿Alguien puede ver lo que está mal (o es esto realmente un error de Java)? ¿Qué tiene de significativo el 1 de noviembre de 1971?¿Por qué se agrega una hora en java.util.Date para las fechas anteriores al 1 de noviembre de 1971?

import java.text.SimpleDateFormat; 
import java.util.Locale; 
import java.util.TimeZone; 

class JavaUtilDateBug 
{ 
    private static void demo() throws Exception 
    { 
     // UK developers usually have the clock on their development machines set 
     // to "Europe/London" (i.e. GMT with daylight saving). Set it explicitly 
     // here so readers in other countries can see the problem too. 
     TimeZone.setDefault(TimeZone.getTimeZone("Europe/London")); 
     Locale.setDefault(Locale.ENGLISH); 

     SimpleDateFormat dateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy"); 
     String strJan1st1970Expected = "Thu Jan 01 00:00:00 GMT 1970"; 
     String strJan1st1970Actual = dateFormat.parse(strJan1st1970Expected).toString(); 
     System.out.println("strJan1st1970Actual: " + strJan1st1970Actual); // -> "Thu Jan 01 01:00:00 GMT 1970" 
     boolean jvmHasDateBug = !strJan1st1970Expected.equals(strJan1st1970Actual); 
     System.out.println("jvmHasDateBug: " + jvmHasDateBug); // -> true 

     // The anomaly only seems to affect times before 1 Nov 1971. 
     final String strNov1st1971 = "Mon Nov 01 00:00:00 GMT 1971"; 
     assert strNov1st1971.equals(dateFormat.parse(strNov1st1971).toString()); 
    } 

    public static void main(String[] args) 
    { 
     try 
     { 
      demo(); 
     } 
     catch (Exception e) 
     { 
      e.printStackTrace(); 
     } 
    } 
} 

entorno Mi Java:

java version "1.6.0_13" 
    Java(TM) SE Runtime Environment (build 1.6.0_13-b03) 
    Java HotSpot(TM) Client VM (build 11.3-b02, mixed mode, sharing) 
+1

Su programa de demostración funciona en máquinas que no están en inglés solo si también configura la configuración regional (de lo contrario, el análisis de la fecha falla). –

+0

Gracias, Michael. Código de demostración actualizado. –

Respuesta

5

Encontré matching bug en la base de datos de errores de Sun. Parece que lo consideran una "inexactitud histórica" ​​(el formato aparentemente debe producir "BST" como zona horaria en lugar de GMT - la hora sería entonces correcta) y no lo arreglará, porque en el fondo, la implementación de TimeZone no puede manejar los lugares cambiando el nombre de su zona horaria.

Como solución temporal, puede establecer explícitamente su zona horaria en GMT en lugar de "Europa/Londres". El problema desaparece.

+0

Parece que el error ya no está disponible en la base de datos de errores. –

13

Es la configuración regional. De http://en.wikipedia.org/wiki/British_Summer_Time

se probó el esquema British Standard Time entre el 27 de octubre de 1968 y el 31 de octubre de 1971, cuando Gran Bretaña se mantuvo en GMT + 1 durante todo el año.

+0

Guau, pensé que habría sido demasiado oscuro para que me respondieran dos veces ... –

+0

Bah. Tuve una respuesta a ma medio cuando me avisaron de sus dos. –

21

Hubo una versión de prueba de British Standard Time entre el 27 de octubre de 1968 y el 31 de octubre de 1971, que sospecho es la causa de este problema.

Hay algunos detalles del juicio aquí:

http://en.wikipedia.org/wiki/British_Summer_Time#Single.2FDouble_Summer_Time

La zona horaria para Europa/Londres en 1ª Ene 1970 fue British Standard Time (GMT + 1) de modo que cuando se utiliza un java.text.SimpleDateFormat para analizar Ene 01 00:00:00 GMT 1970 genera el valor de época correcto igual a Jan 01 01:00:00 1970 en BST.

Entonces, debido a la Crappiness de java.util.Date, cuando se llama java.util.Date.toString() se utiliza la zona horaria predeterminada para el actual local de ahora, que ha cambiado a GMT y se obtiene Ene 01 01:00:00 GMT 1970.

+0

Interesante. Aún no está claro por qué no es simétrica, sin embargo, si alimentas en "Thu Jan 01 00:00:00 GMT 1970" deberías obtener lo mismo. –

+0

Esto no es un problema con java.util.Date's toString(), el comportamiento no es diferente cuando lo formatea utilizando el mismo SimpleDateFormat que utilizó para analizar. Vea mi respuesta para que Sun se encargue de esto. –

+0

Hola, Michael: echa un vistazo al método normalize() java.util.Date. Se llama desde el método toString() y realiza la llamada TimeZone.getDefaultRef() para obtener la zona horaria. Esa parece la causa, ¿verdad? –

0

Esto no es un error.

Ha establecido su zona horaria por defecto a BST que es (GMT + 1), la fecha GMT de Jan 1 1970 00:00:00, al analizar esta fecha con BST zona horaria como predeterminado, que siempre muestra el tiempo en función de su zona horaria actual (auto Se aplica desplazado de GMT) .

En este caso fue GMT + 1 por lo que su resultado fue una hora de descanso.

Cuestiones relacionadas