2017-10-16 1 views
7

Je rencontre un problème lors de la conversion d'une date qui n'existe pas réellement à l'aide de l'annotation @DateTimeFormat.@DateTimeFormat avec erreur d'heure d'été lors de la conversion

Par exemple, quand je mets la date 15/10/2017, avec l'annotation dans mon entité comme suit:

@Column(nullable = false) 
@NotNull 
@DateTimeFormat(pattern = "dd/MM/yyyy") 
private Date dataVisita; 

Je reçois l'erreur:

Failed To Convert Property Value Of Type Java.Lang.String To Required Type Java.Util.Date For Property DataVisita; 
Nested Exception Is Org.Springframework.Core.Convert.ConversionFailedException: 
    Failed To Convert From Type Java.Lang.String To Type @Javax.Persistence.Column @Javax.Validation.Constraints.NotNull @Org.Springframework.Format.Annotation.DateTimeFormat Java.Util.Date For Value 15/10/2017; 
Nested Exception Is Java.Lang.IllegalArgumentException: 
    Cannot Parse "15/10/2017": Illegal Instant Due To Time Zone Offset Transition (America/Sao_Paulo) 

Je comprends que la erreur me dit que la date 15/10/2017 00:00:00 n'existe pas réellement, mais je veux convertir en 15/10/2017 01:00:00, en ignorant de cette façon le problème et en trouvant la date correspondante.

Y a-t-il un moyen pour moi de surcharger l'annotation @DateTimeFormat ou un moyen de pointer le formateur pour qu'il soit indulgent?

+1

'Signalez ce que vous dites et dites ce que vous voulez dire' Vous essayez actuellement de mettre une date dans un objet qui représente la date et l'heure. Pouvez-vous utiliser LocalDate ou êtes-vous coincé avec Date? – mpkorstanje

+0

Vous pouvez créer un désérialiseur personnalisé. AFAIR utilise Jackson sous le capot. L'annotation 'JsonDeserialize' devrait aider. [Exemple Jackson-Deserialization.] (Http://www.baeldung.com/jackson-deserialization) –

+0

Essayez d'utiliser '@DateTimeFormat (iso = ISO.DATE_TIME)', il n'ignorera pas l'heure dans la chaîne –

Répondre

3

Essayez ceci:

@Column(nullable = false)

@NotNull

@DateTimeFormat(pattern = "dd/MM/yyyy HH:mm:ss")

private Date dataVisita;

Il semble faire ce que vous voulez (régler midi 00-à-01:00), vous aurez besoin de mettre en œuvre un validator comme suit:

public class PersonValidator implements Validator { 

    /** 
    * This Validator validates *just* Person instances 
    */ 
    public boolean supports(Class clazz) { 
     return Date.class.equals(clazz); 
    } 

    public void validate(Object obj, Errors e) { 
     String dateString = (String) obj; 
     DateTimeFormatter fmt = DateTimeFormat.forPattern("dd/MM/yyyy HH:mm:ss"); 
     DateTime ourDate = null; 
     try { 
      fmt.parseDateTime(dateString); 
     } catch (IllegalArgumentException e) { 
      // massage your hour here 
     } finally { 
      ourDate = fmt.parseDateTime(dateString); 
     } 
    } 
} 
+0

Bonne capture, @ OleV.V. – hd1

0

Si vous voulez utiliser DateTimeFormat qui est Java 8 classe et une partie de nouveau (bien depuis java 8) cadre « de java.time » vous avez probablement besoin d'utiliser Java 8 Date de classes:

DATE:
java.time.LocalDate

HEURE:
java.time.LocalTime, java.time.OffsetTime

timestamp:
java.time.Instant, java.time.LocalDateTime, java.time. OffsetDateTime et java.time.ZonedDateTime

De plus, quel ORM utilisez-vous avec votre framework Spring? Données de printemps, hiberner ou autre chose? Si vous utilisez Hibernate, puis consultez le guide de l'utilisateur Mise en veille prolongée: Mapping Date/Time Values

0

Selon la façon dont vous stockez vos dates dans DB, et votre fuseau horaire du serveur, la solution serait de définir votre fuseau horaire par défaut UTC lors de l'initialisation du printemps, en utilisant la code suivant:

TimeZone.setDefault(TimeZone.getTimeZone("UTC"));

1

Pour moi, vous ne devriez pas gâcher directement avec les paramètres régionaux du système. C'est ce que votre problème est vraiment.

Je veux dire que vous n'avez pas fourni de fuseau horaire, vous utilisez donc celui du serveur. Sur ce serveur avec sa config, ce sera ce jour/date. Sur un autre serveur ce serait un autre jour/date. Assurez-vous que vous travaillez en UTC (donc pas d'économie de lumière du jour et tous) ou un environnement local explicite que le client a fourni en entrée, utilisez une date locale pour stocker ... Soit comme ça et quand vous avez besoin pour comparer les dates, convertissez-le en UTC. De cette façon, le problème disparaîtrait.Une solution rapide consiste à s'assurer que votre serveur utilise UTC, mais à long terme, vous devez toujours contrôler les paramètres régionaux avec lesquels vous travaillez, donc la date fournie doit être UTC ou c'est une date locale et un autre champ fournit le fuseau horaire .

+0

J'ai un paramètre régional configuré par défaut pour l'application "pt_BR", donc il utilisera toujours cela pour les dates – Thiesen

0

Cela devrait être très simple.

Le problème ici est que vous transmettez une valeur String pour un objet Date. Voici la documentation de l'annotation en question:

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/format/annotation/DateTimeFormat.html

En termes simples ici sont les types requis: java.util.Date, java.util.Calendar, java.lang.Long, types de valeurs Joda-Time

Une manière très naïve:

SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy"); 
Date destnationDateToBeSaved = sdf.parse("15/10/2017"); 

Méthode recommandée:

utilisation:

@DateTimeFormat(iso = ISO.DATE_TIME) 
private ZonedDateTime zonedDateTime; 

et

// 'yyyy-MMM-dd HH:mm:ss' pattern or if preferred ISO 
ZonedDateTime destnationDateToBeSaved= ZonedDateTime.parse("2017-Oct-15 23:35:05", DateTimeFormatter.ofPattern("yyyy-MMM-dd HH:mm:ss").withZone(ZoneId.of("UTC"))); 

Hope that helps!