2011-11-04 9 views
5

Sto utilizzando Spring MVC su una macchina che ha l'ora legale configurata (fuso orario America/Sao_Paulo). Nella mia classe forma ho usato il DateTimeFormat annotazioni per configurare l'uscita del mio Data:Errore di conversione di Spring @DateTimeFormat con l'ora legale

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

Durante il debug sto ottenendo la data 16/10/2011 (gg/mm/aaaa) che è l'inizio della luce del giorno tempo, ma Spring lo converte nel 2011-10-15. Perché?

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' 

vedo questa domanda: @DateTimeFormat in Spring produces off-by-one day error

ma Spring 3 utilizza Joda-Time e ho Joda-tempo-2.0.jar nel mio percorso di classe in modo da non so il motivo per cui questo accade e come posso risolvilo.

[EDIT]

Ho provato la creazione di oggetti LocalData, e trovato qualcosa:

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 

Sembra che il primo approccio è pensare che il tempo è in UTC, perché il debug mi possiamo vedere che Joda usa il metodo convertUTCToLocal della classe DateTimeZone.

Forse questo è l'impostazione predefinita anche per la primavera, si aspetta anche una data in UTC e sto passando la data BRT.

Quindi penso che la mia soluzione sia modificare gli oggetti in LocalDate e utilizzare il secondo modo per creare l'istanza di questo oggetto.

+0

Non è chiaro: stai convertendo * in * una stringa, o * da * una stringa? Inoltre, se questa è solo una data, sarebbe meglio usare il tipo 'LocalDate' di Joda. –

+0

@JonSkeet è una data da stringere. Posso impostare LocalDate con @DateTimeFormat? –

+0

Mi aspetterei di sì. Tieni presente che il valore di "Data" sembra essere mezzanotte * BRST * del 16 ottobre ... è deliberato? Certo, è strano che venga formattato come il 15 ottobre ... ma in generale sarebbe meglio evitare i fusi orari se si utilizzano le date :) –

risposta

5

Questo potrebbe rispondere a parti della tua domanda.

Quando si dispone di un oggetto java.util.Data che verrà stampato nel fuso orario del sistema in toString. Quindi, se imposti una data in UTC 2011-10-16 00:00:00 che verrà convertita in un timestamp UTC internamente nella data. toString stamperà quel timestamp nel fuso orario locale e ci vorranno un paio d'ore dopo il UTC (da quando San Paolo è a ovest di Londra) quindi all'incirca tra il 2011-10-15 e il 22:00:00. Questo è ciò che vedrai nei breakpoint e nelle stampe di debug. I dati potrebbero essere comunque corretti internamente.

Se ha scoperto che l'unico vero modo di Date di stampa è attraverso SimpleDateFormat come questo:

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 
    } 

Ora la stampa avrà un aspetto molto confusa

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

ma lascia camminare attraverso di essa.

  1. In primo luogo, il mio SimpleDateFormat ottiene un formato e l'ho impostato per assumere tutto il testo in entrata e in uscita nel fuso orario UTC.
  2. Quando analizzo la data 2011-10-16 00:00:00 che verrà interpretata come UTC ma quando stampo java utilizza la mia locale (CET) per stampare come 2011-10-16 01:00:00 , è anche quello che vedrei su un punto di interruzione
  3. Quando creo una nuova data() quella data sarà nella mia lingua e quando stamperò mostrerà 15:47 (la mia ora corrente) ma quando formatto con il mio SimpleDateFormat basato sul fuso orario mostrerà l'ora in UTC.

Detto questo, Java e le date saranno confondere fino a quando si tira i capelli :)

Spero che questo aiuti un po '.

+0

Spiegazione molto interessante Probabilmente Spring sta forzando un certo fuso orario.Sarà se posso usare SimpleDateFormat come conversatore invece di GenericConversionService –

+0

Sono contento che questo aiuti. Penso che questo sia quello che stai cercando http://static.springsource.org/spring/docs/3.0.6.RELEASE/javadoc-api/org/springframework/beans/propertyeditors/ CustomDateEditor.html –