2011-11-04 23 views
5

Estoy utilizando Spring MVC en una máquina que tiene configurado el horario de verano (América/Sao_Paulo zona horaria). En mi clase de formulario He utilizado el DateTimeFormat anotación para configurar la salida de mi Fecha:Spring @DateTimeFormat error de conversión con horario de verano

public class JustificativaOcorForm { 
    ... 
    @NotNull 
    @DateTimeFormat(pattern="yyyy-MM-dd") 
    private Date dataMarcacao; 
    ... 
} 

Mientras se depura Me estoy poniendo la fecha 16/10/2011 (dd/mm/aaaa), que es el comienzo de la luz del día tiempo, pero Spring lo convierte en 2011-10-15. ¿Por qué?

2011-11-04 16:35:31,965 [http-8080-Processor25] DEBUG org.springframework.core.convert.support.GenericConversionService - Converting value Sun Oct 16 00:00:00 BRST 2011 of [TypeDescriptor @javax.validation.constraints.NotNull @org.springframework.format.annotation.DateTimeFormat java.util.Date] to [TypeDescriptor java.lang.Long] 
2011-11-04 16:35:31,965 [http-8080-Processor25] DEBUG org.springframework.core.convert.support.GenericConversionService - Converted to 1318730400000 
2011-11-04 16:35:32,010 [http-8080-Processor25] DEBUG org.springframework.core.convert.support.GenericConversionService - Converted to '2011-10-15' 

veo esta pregunta: @DateTimeFormat in Spring produces off-by-one day error

pero Spring 3 utiliza Joda-Time y tengo joda-tiempo-2.0.jar en mi ruta de clase, así que no sé por qué ocurre esto y cómo puedo resuélvelo.

[EDIT]

He probado la creación de objetos LocalData, y encontré algo:

LocalDate ld = new LocalDate(new SimpleDateFormat("dd/MM/yyyy").parse("16/10/2011").getTime()); 
System.out.println(new SimpleDateFormat("dd/MM/yyyy HH:mm:ss Z z").format(ld.toDate()) ); 
//prints 15/10/2011 00:00:00 -0200 BRST 

LocalDate ld2 = new LocalDate(2011,10,16); 
System.out.println(new SimpleDateFormat("dd/MM/yyyy HH:mm:ss Z z").format(ld2.toDate()) ); 
//prints 16/10/2011 00:00:00 -0200 BRST 

Parece que el primer enfoque es pensar que el tiempo está en UTC, debido a que la depuración Puede ver que Joda usa el método convertUTCToLocal de la clase DateTimeZone.

Tal vez este es el valor predeterminado de la primavera también, él espera una fecha en UTC también y estoy pasando la fecha de BRT.

Así que creo que mi solución es cambiar los objetos a LocalDate y usar la segunda forma de crear la instancia de este objeto.

+0

No está claro, ¿está convirtiendo * en * una cadena, o * de * una cadena? Además, si esto solo pretende ser una fecha, sería mejor usar el tipo 'LocalDate' de Joda. –

+0

@JonSkeet es una fecha para cadena. Puedo establecer LocalDate con @DateTimeFormat? –

+0

Ciertamente lo esperaría. Tenga en cuenta que su valor de 'Fecha' parece ser medianoche * BRST * el 16 de octubre ... ¿es deliberado? Es cierto que es extraño que se formatee como el 15 de octubre ... pero sería mejor evitar las zonas horarias por completo si está usando fechas :) –

Respuesta

5

Esto podría responder a partes de su pregunta.

Cuando tenga un objeto java.util.Data que se imprimirá en la zona horaria de su sistema dentro de toString. Por lo tanto, si establece una fecha que esté en UTC 2011-10-16 00:00:00 que se va a convertir en una marca de tiempo UTC internamente en la Fecha. toString imprimirá esa marca de tiempo en su zona horaria local y eso va a ser un par de horas después de UTC (ya que Sao Paulo está al oeste de Londres) por lo que aproximadamente 2011-10-15 22:00:00. Eso es lo que verá en los puntos de quiebre y las impresiones de depuración. Sin embargo, los datos aún podrían ser correctos internamente.

Si encuentra que la única forma real de fechas de impresión es a través de SimpleDateFormat así:

SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
    dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); 
    try { 
     Date dateInUTC = dateFormat.parse("2011-10-16 00:00:00"); 
     Date currentDate = new Date(); 
     String stringInUTC = dateFormat.format(currentDate); 
     System.out.println(dateInUTC); 
     System.out.println(currentDate); 
     System.out.println(stringInUTC); 
    } 
    catch (ParseException e) { 
     // not too worry, I wrote a nice date 
    } 

Ahora la impresión parecerá muy confuso

Sun Oct 16 01:00:00 CET 2011 
Thu Nov 10 15:47:46 CET 2011 
2011-11-10 14:47:46 

pero permite caminar a través de él.

  1. Primero, mi SimpleDateFormat obtiene un formato y lo configuro para suponer que todo el texto dentro y fuera está en la zona horaria UTC.
  2. Cuando analizo la fecha 2011-10-16 00:00:00 que se interpretará como UTC, pero cuando imprimo, java usa mi configuración regional (CET) para imprimir esto como 2011-10-16 01:00:00 , eso también es lo que vería en un punto de ruptura
  3. Cuando creo una nueva Fecha() esa Fecha estará en mi localidad y cuando la imprima aparecerá 15:47 (mi hora actual) pero cuando formule con mi zona horaria consciente SimpleDateFormat mostrará la hora en UTC.

Dicho esto, Java y fechas se confunda usted hasta que se tire de los pelos :)

Espero que esto ayude un poco.

+0

¡Una explicación muy interesante! Probablemente Spring forza un poco de zona horaria. Veré si puedo usar SimpleDateFormat como conversor en lugar de GenericConversionService –

+0

Me alegra que ayude. Creo que esto es lo que está buscando http://static.springsource.org/spring/docs/3.0.6.RELEASE/javadoc-api/org/springframework/beans/propertyeditors/ CustomDateEditor.html –

Cuestiones relacionadas