2017-10-09 91 views
1

我正在開發處理日期的彈簧引導應用程序。當我提交具有startDateTimeendDateTime(兩者都是java.util.Date類型的)約會對象我送的格式是這樣的:使用Spring引導和傑克遜日期時區

{ 
    "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", 
} 

當數據在數據庫堅持它與正確的時區,當我嘗試找回我的數據傳回,他們似乎正確的,當我在調試然而,一旦被傑克遜系列化我有這些的輸出值:

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

如何配置傑克遜做出自帶的時區的使用我的資料庫中的數據?

------更新---------

我想答案與OffsetDateTime但輸出是相當奇怪:

"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 
    } 

我想有什麼像:

2017-10-09T22:43:07.109 + 0300

+0

使用DateTime類是更適合這種情況 – CodeIsLife

+0

如果OffsetDateTime字段(如下面的答案中所示),您是否使用了'JsonFormat'註釋? – 2017-10-09 19:55:29

+0

是的,我添加了這個註解,但仍然沒有工作 – Habchi

回答

2

java.util.Datedoesn't have any timezone information。將String反序列化爲Date後,將會丟失偏移+0300:該日期只保留時間戳值,並且無法知道其來源的原始時區是什麼。

如果輸出必須始終+03:00偏移,您可以直接在各自領域設置,使用com.fasterxml.jackson.annotation.JsonFormat註釋:

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

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

這樣,日期字段將永遠被序列化到+03:00偏移:

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

如果輸入可以是任何其它偏移量(不僅+03:00)和你想保留它,java.util.Date不是理想的類型。一種選擇是使用Jackson Modules Java 8,如果你使用的是Java> = 8

對於Java 6和7,還有的ThreeTen Backport和相應的Jackson module - 我沒有測試過,雖然,但代碼可能是相似,因爲ThreeTen Backport包含相同的類和方法,所以只有軟件包不同 - (在Java 8中爲java.time,在ThreeTen Backport中爲org.threeten.bp

要保存日期,時間和偏移量,最好的選擇是OffsetDateTime類。所以,你只需要改變的字段類型,並設置相應的格式它:

@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; 

在對象映射,你還必須註冊JavaTimeModule和禁用ADJUST_DATES_TO_CONTEXT_TIME_ZONE feature,所以偏移被保留(默認行爲是轉換爲Jackson上下文的時區,這可能與輸入中使用的時區不同 - 通過禁用此功能,偏移量將保留)。

可以使用JacksonConfigurator(如explained in this answer),做這些配置:

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

這種配置通常是不夠的,但你也可以設置SerializationFeature.WRITE_DATES_AS_TIMESTAMPSfalse爲好,以防萬一。


如果您仍然需要java.util.Date工作,你可以使用API​​來/將其轉換。在Java 8,有一個新的Date.from方法:

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

而且在ThreeTen反向移植,還有的org.threeten.bp.DateTimeUtils類:

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

要將Date轉換回OffsetDateTime,不過,它更棘手。 Date對象沒有時區信息,因此無法知道原始偏移量。一種選擇是保留原來在一個單獨的可變偏移:

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

然後,您可以轉換DateInstant,然後將其轉換爲原始偏移:

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

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

spring.jackson.time-zone配置如何?註釋適用於我,而春季配置則不適用。 –