2017-10-09 3 views
1

Je suis en train de développer une application de démarrage à ressort qui gère les dates. Quand je soumets un objet de rendez-vous qui a un startDateTime et un endDateTime (Les deux sont de type java.util.Date) J'envoie un format comme celui-ci:Date timezone avec Spring boot et Jackson

{ 
    "lastName": "Jhon", 
    "firstName": "Doe", 
    "email": "[email protected]", 
    "description": "MyDescription", 
    "startDateTime": "2017-10-09T22:43:07.109+0300", 
    "endDateTime": "2017-10-09T21:40:07.109+0300", 
} 

Lorsque des données est conservée dans la base de données, il est avec le fuseau horaire correct, lorsque je tente de récupérer mes données, ils semblent correctes quand je le débogage cependant, une fois qu'ils sont sérialisés par Jackson J'ai une sortie avec ceux-ci comme valeur:

"startDateTime": "2017-10-09T19:43:07.109+0000", 
"endDateTime": "2017-10-09T18:40:07.109+0000", 

Comment puis-je configurer Jackson pour faire usage de fuseau horaire qui vient avec les données de mon référentiel?

------ Mise à jour ---------

J'ai essayé la réponse avec OffsetDateTime mais la sortie est assez bizarre:

"startDateTime": { 
     "offset": { 
      "totalSeconds": 7200, 
      "id": "+02:00", 
      "rules": { 
       "fixedOffset": true, 
       "transitionRules": [], 
       "transitions": [] 
      } 
     }, 
     "month": "OCTOBER", 
     "year": 2017, 
     "hour": 21, 
     "minute": 49, 
     "nano": 654000000, 
     "second": 15, 
     "dayOfMonth": 9, 
     "dayOfWeek": "MONDAY", 
     "dayOfYear": 282, 
     "monthValue": 10 
    } 

je voudrais avoir quelque chose comme:

2017-10-09T22: 43: 07,109 + 0300

+0

usage classe DateTime qui est plus approprié pour ce cas – CodeIsLife

+0

Avez-vous utilisé l'annotation 'JsonFormat' si les champs' OffsetDateTime' (comme dans ma réponse ci-dessous)? –

+0

Oui, j'ai ajouté cette annotation, mais ne fonctionnait toujours pas – Habchi

Répondre

2

A java.util.Datedoesn't have any timezone information. Une fois que vous désérialisez un String en Date, le décalage +0300 est perdu: la date conserve uniquement la valeur d'horodatage et ne peut pas savoir quel est le fuseau horaire d'origine.

Si la sortie doit toujours être en +03:00 décalage, vous pouvez définir directement dans les champs respectifs, en utilisant la com.fasterxml.jackson.annotation.JsonFormat annotation:

@JsonFormat(timezone = "GMT+03:00") 
private Date startDateTime; 

@JsonFormat(timezone = "GMT+03:00") 
private Date endDateTime; 

Avec cela, les champs de date seront toujours sérialisés à +03:00 offset:

{ 
    "startDateTime":"2017-10-09T22:43:07.109+0300", 
    "endDateTime":"2017-10-09T21:40:07.109+0300" 
} 

Si les entrées peuvent être tout autre décalage (non seulement +03:00) et vous voulez le préserver, le java.util.Date n'est pas le type idéal. Une alternative consiste à utiliser Jackson Modules Java 8, si vous utilisez Java> = 8.

Pour Java 6 et 7, il y a le ThreeTen Backport et correspondant Jackson module - Je ne l'ai pas testé, mais, mais le code peut être similaire , car le BackTort ThreeTen contient les mêmes classes et méthodes, seul le package est différent - (Java 8 est java.time et dans ThreeTen Backport est org.threeten.bp).

Pour préserver la date, l'heure et le décalage, la meilleure alternative est la classe OffsetDateTime. Donc, il vous suffit de modifier les champs de type et définir le format qui lui correspond:

@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXX") 
private OffsetDateTime startDateTime; 

@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXX") 
private OffsetDateTime endDateTime; 

Dans le mappeur d'objets, vous devez également enregistrer le JavaTimeModule et désactiver le ADJUST_DATES_TO_CONTEXT_TIME_ZONE feature, de sorte que les décalages sont préservés (le comportement par défaut est pour convertir au fuseau horaire du contexte de Jackson, qui pourrait ne pas être le même utilisé dans les entrées - en désactivant ceci, le décalage est préservé).

Vous pouvez utiliser un JacksonConfigurator (comme explained in this answer) et faire ces configurations:

ObjectMapper om = new ObjectMapper(); 
om.registerModule(new JavaTimeModule()); 
om.configure(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE, false); 

Cette configuration est généralement suffisant, mais vous pouvez également définir SerializationFeature.WRITE_DATES_AS_TIMESTAMPS-false aussi bien, juste au cas où.


Si vous avez besoin de travailler avec java.util.Date, vous pouvez utiliser l'API pour convertir de/vers elle. En Java 8, il y a la nouvelle méthode Date.from:

// convert to java.util.Date 
public Date getStartAsJavaUtilDate() { 
    return Date.from(startDateTime.toInstant()); 
} 

Et ThreeTen Backport, il y a la classe org.threeten.bp.DateTimeUtils:

// convert to java.util.Date 
DateTimeUtils.toDate(startDateTime.toInstant()); 

Pour convertir un Date retour à OffsetDateTime, cependant, il est plus délicat. L'objet Date n'a pas d'informations de fuseau horaire, il ne peut donc pas connaître le décalage d'origine. Une alternative consiste à maintenir le décalage d'origine dans une variable séparée:

// keep the original offset 
ZoneOffset startDateOffset = startDateTime.getOffset(); 

Ensuite, vous pouvez convertir le Date à Instant, puis le convertir à l'original offset:

// convert java.util.Date to original offset (Java 8) 
startDateTime = date.toInstant().atOffset(startDateOffset); 

// ThreeTen Backport 
startDateTime = DateTimeUtils.toInstant(date).atOffset(startDateOffset); 
+0

qu'en est-il de spring.jackson.time-zone config? L'annotation fonctionne pour moi tandis que la config de printemps ne dose pas. –