我被ZonedTime的Aeson和Servant转换搞糊涂了。
对于我的Servant应用程序,我在url:.../2016-12-18T07:51:00+03:00/...中提供了一些时间。
Servant可以使用... :> Capture "zt" ZonedTime :> ...轻松地将其转换为ZonedTime。
然后我的应用程序做了一些计算,在json-ZonedTime中,我想要将这个时间和其他一些响应时间返回给客户端-以防客户端再次将这些时间提供给我的应用程序。
如果输入时区不是零+0X:00 (X /= 0),那么在输出上我也会得到+0X:00,但如果在输入上我给出了.../2016-12-18T07:51:00+00:00/...,那么作为响应,我会得到2016-12-18T07:51:00Z。如果我再次尝试使用.../2016-12-18T07:51:00Z/...将此字符串提供给Servant,则Servant无法将其转换为ZonedTime。实际上是返回HTTP 400 (Bad Request)。
为什么?干什么用?For what?
发布于 2016-12-23 05:09:31
ISO 8601是JSON中使用的时间的标准文本表示。当时区为UTC时,"+00:00“或"Z”是有效的时区后缀。在ISO 8601中,如果是UTC,则使用"Z“后缀输出时间,否则使用"+xx:xx”后缀。不幸的是,Servant (实际上是Web.HttpApiData)使用了一种简单的方法,从不允许使用"Z“后缀的URL片段中解析ZonedTime。如果您解析UTCTime,那么它将使用(并且需要) "Z“后缀。
您可以按如下方式为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 )。
发布于 2016-12-23 08:22:38
好的。
所以,一旦Servant正确地将...Z符号解析为UTCTime,我就编写了另一行捕获代码:
:<|> "myendpoint" :> Capture "zt" ZonedTime :> ...
:<|> "myendpoint" :> Capture "utct" UTCTime :> ...并制定了相应的处理程序。使用这个带有+xx:xx的字面值作为ZonedTime并转到一个处理程序,使用Z的字面值由第二行获取并转到第二个处理程序,这与第一个处理程序的功能相同,但会动态地将UTC转换为Zoned。
更新
我开始明白,我的系统是如何工作的,这导致了这样一个事实,在URL中,我可能有不同的字符串编码时间。
作为时区的
+03:00,如果是用于协调世界时,则仅为Z。2016-12-09T15:04:26.349857693845+05:00一样具有小数秒
ZonedTime的标准Capture既不能将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)我处理字符串问题,将其替换为+00:00
%Q捕获秒的小数部分。https://stackoverflow.com/questions/41275758
复制相似问题