5

我正在尝试为 Data.Time.Calendar's Day 类型创建一个 FromJSON 实例。我对这些类型感到困惑,这似乎是一个应该解决的常见情况。

所以 Day 类型表示修改后的儒略日期。并且 Data.Time.Calendar 模块定义了“showGregorian”,它将修改后的儒略日期转换为公历日期并输出字符串 ISO 8601 表示。

问题是 Data.Time.Calendar 没有很好的方法将 ISO 8601 解析为公历日期。如果我使用 ParseTime 类,我只能传递字符串格式,而不是字符串代表日期的日历。因此,实际上,我将传入“20140502”,ParseTime 类将该字符串视为修改后的 Julian 日期的字符串表示形式。

看来这应该是一个已解决的问题。理想情况下,我想要一个不使用日期时间的解决方案。我的模型使用公历日期,因为这就是我所需要的,而这些就是我将要比较、搜索等的东西。

当然,当我只需要日历日时使用日历日的全部原因是这样我就不必考虑如何比较和转换它们,但我想那是另一天的抱怨。

附录:

天数定义为:

-- | The Modified Julian Day is a standard count of days, with zero being the day 1858-11-17.
newtype Day = ModifiedJulianDay {toModifiedJulianDay :: Integer} deriving (Eq,Ord)

这让我相信一天不是物理的一天,而是 MJD 日历中的一天(根据公开的文档应该告诉我们类型代表什么,而不是类型的表示的原则)。

4

2 回答 2

2

GHC.Generics模块使这类问题很容易解决。

{-# language DeriveGeneric #-}
{-# language StandaloneDeriving #-}

import Data.Aeson
import Data.Time.Calendar

import GHC.Generics

deriving instance Generic Day

instance ToJSON  Day
instance FromJSON  Day

虽然在阅读您的评论时:

我追求的是一种将 ISO 8601 日期解析为“日”的无错误方法,该方法使用修改后的儒略历。

这可能不是您正在寻找的解决方案。

于 2014-05-03T05:19:15.880 回答
2

为什么不parseTime完全按照你的意愿去做? parseTime defaultTimeLocale "%F"正好是 的倒数(最多JustshowGregorian,如您可以粘贴到 GHCi 中的以下代码段所示。

import System.Locale 
import Data.Time.Format 
import Data.Time.Calendar

let test = parseTime defaultTimeLocale "%F" . showGregorian :: Day -> Maybe Day
let notIdentity x = case test x of { Nothing -> True; Just x' -> x /= x' }
filter notIdentity [fromGregorian 0 1 1..fromGregorian 3000 12 31]
于 2014-05-03T08:39:54.990 回答