1

我对. Aeson_ServantZonedTime

对于我的Servant应用程序,我在 url: 中给出了一些时间.../2016-12-18T07:51:00+03:00/...

Servant轻松将其转换为ZonedTimewith ... :> Capture "zt" ZonedTime :> ...

然后我的应用程序会进行一些计算,并且在 json-response 中我想将这个和其他一些ZonedTimes 回馈给客户——以防客户想再次将这些时间给我的应用程序。

如果输入时区不为零+0X:00(X / = 0),那么在输出上我也会得到+0X:00,但如果在输入上我给出.../2016-12-18T07:51:00+00:00/...,那么作为响应我得到2016-12-18T07:51:00Z。如果我尝试Servant再次将此字符串提供给.../2016-12-18T07:51:00Z/...,则Servant无法将其转换为ZonedTime. 其实是退货HTTP 400 (Bad Request)

为什么?做什么的?

4

2 回答 2

0

ISO 8601是 JSON 中使用的时间的标准文本表示。当时区为 UTC 时,“+00:00”或“Z”是有效的时区后缀。如果是 UTC,则 Aeson 在 ISO 8601 中使用“Z”后缀输出时间,否则使用“+xx:xx”后缀。不幸的是,Servant(实际上是)使用了一种从不允许使用“Z”后缀的 URL 片段Web.HttpApiData中解析的简单方法。ZonedTime如果您UTCTime改为解析 a ,则它使用(并且需要)“Z”后缀。

您可以为以下定义一个新类型别名,ZonedTime通过尝试解析为 aZonedTime和 - 失败 - aUTCTime转换来处理这两种格式:

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)。

于 2016-12-22T21:09:30.623 回答
0

好的。

因此,只要...ZServant 正确解析符号 as UTCTime,我就制作了另一条捕获线:

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

并做了相应的处理程序。使用带有+xx:xxget 的文字ZonedTime并转到一个处理程序,而带有文字的文字Z 由第二行采用并转到第二个处理程序,这与第一个处理程序相同,但会即时转换UTCZoned


更新

我开始明白,我的系统如何工作的方式导致了这样一个事实,即在 URL 中我可能有不同的字符串编码时间变化。

  1. 作为一个时区可能是+03:00或只是Z如果它是 UTC。
  2. 我可能有小数秒2016-12-09T15:04:26.349857693845+05:00

标准既不理解为时区,也不理解Capture为小数秒。ZonedTimeZ

所以我以某种方式朝着这个方向做了,正如这里另一个答案中所建议的那样。

我只放了一条捕获线

"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捕获秒的小数部分。
于 2016-12-23T00:22:38.233 回答