2016-12-22 31 views
1

我被AesonServant轉換爲ZonedTimeZonedTime從JSON到JSON

給我的Servant應用程序我給了一些時間在網址:.../2016-12-18T07:51:00+03:00/...

Servant很容易將它轉換爲ZonedTime... :> Capture "zt" ZonedTime :> ...

然後我的應用程序做了一些計算和json響應我想回饋給客戶端和其他一些ZonedTime s - 如果客戶想要再次給我的應用程序這些時間。

如果輸入時區是不爲零+0X:00(X/= 0),然後在輸出I也得到+0X:00,但如果在輸入I給.../2016-12-18T07:51:00+00:00/...,然後響應我得到2016-12-18T07:51:00Z。如果我嘗試再次使用.../2016-12-18T07:51:00Z/...將此字符串提供給Servant,則Servant無法將其轉換爲ZonedTime。實際上是返回HTTP 400 (Bad Request)

爲什麼?做什麼的?

回答

0

ISO 8601是JSON中使用時間的標準文本表示。當時區是UTC時,「+00:00」或「Z」是有效的時區後綴。它看起來像Aeson在ISO 8601中輸出時間,如果它是UTC,則使用「Z」後綴,否則輸出「+ xx:xx」後綴。不幸的是,僕人(實際上,Web.HttpApiData)使用了一種天真的方法來解析來自不允許「Z」後綴的URL片段的ZonedTime。如果你解析UTCTime,那麼它使用(並且需要)「Z」後綴。

您可以定義NEWTYPE別名ZonedTime如下,通過試圖解析爲ZonedTime和處理這兩種格式 - 做不到這一點 - 與轉化UTCTime

module ZonedTimeTest where 

import Data.Time.LocalTime 
import Servant.API 

newtype ZonedTime' = ZonedTime' { getZonedTime :: ZonedTime } 

instance FromHttpApiData ZonedTime' where 
    parseUrlPiece u =  ZonedTime' <$> parseUrlPiece u   -- "...+xx:xx" 
        <!> ZonedTime' . fromUTC <$> parseUrlPiece u -- "...Z" 
    where fromUTC = utcToZonedTime utc 
      infixl 3 <!> 
      Left _ <!> y = y 
      x  <!> _ = x 

然後Capture "zt" ZonedTime'應同時處理格式(儘管您需要在適當的位置將ZonedTime'解包爲ZonedTime)。

+0

啊哈。明確。我將首先嚐試使用'utctime'而不是'zonedtime'來創建新的捕捉線,並且將會看到Servant是否將使用兩行之間的分派進行管理。 – Dahan

0

好的。

所以,只要...Z符號正確的僕人解析爲UTCTime,我只是做了另一個捕獲行:

:<|> "myendpoint" :> Capture "zt" ZonedTime :> ... 
:<|> "myendpoint" :> Capture "utct" UTCTime :> ... 

並做出了相應的處理程序。將這個帶有+xx:xx的文字看作ZonedTime並且轉到一個處理程序,並且在第二行採用文字Z並轉到第二處理程序,它與第一個處理程序執行的操作相同,但在運行中將UTC轉換爲Zoned


更新

我才明白,那這樣,我的系統是如何工作導致了一個事實,即在URL我可能有串編碼時間不同的變化。

  1. 作爲時區可能是+03:00或只是Z如果是UTC。
  2. 我可能有零點幾秒,就像2016-12-09T15:04:26.349857693845+05:00

標準CaptureZonedTime不理解也不Z的時區,也沒有小數秒。

所以我做了一個方向,正如另一個答案在這裏提出的。

我只放一個捕獲線

"daymonth" :> Capture "zt" ZonedTime' :> Capture "fl" Double :> Get '[JSON] Value 

和我做新型ZonedTime',就是對我做的一切。

newtype ZonedTime' = ZonedTime' { unwrap :: ZonedTime } 

instance FromHttpApiData ZonedTime' where 
    parseUrlPiece text = Right zt 
    where 
     strRaw = unpack text 
     str = subRegex (mkRegex "Z$") strRaw "+00:00" 
     zt = ZonedTime' (parseTimeOrError False defaultTimeLocale "%Y-%m-%dT%H:%M:%S%Q%z" str) 
  1. 我處理Z問題,隨着+00:00
  2. 然後我寫手動解析字符串,給格式字符串,秒其中%Q卡子小數部分代它。