简体   繁体   English

Haskell日期解析

[英]Haskell Date parsing

I'm trying to make a FromJSON instance for Data.Time.Calendar's Day type. 我正在尝试为Data.Time.Calendar的Day类型创建一个FromJSON实例。 I am confused about the types, and this seems like a common enough situation that it ought to be solved. 我对这些类型感到困惑,这似乎是一个应该解决的常见情况。

So the Day type represents a modified Julian date. 因此,Day类型表示修改后的Julian日期。 And the Data.Time.Calendar module defines "showGregorian", which converts the modified Julian date into a Gregorian date and outputs a String ISO 8601 representation. Data.Time.Calendar模块定义“showGregorian”,它将修改后的Julian日期转换为公历日期并输出String ISO 8601表示。

The trouble is that Data.Time.Calendar doesn't have a good way to parse an ISO 8601 into a Gregorian date. 麻烦的是,Data.Time.Calendar没有很好的方法将ISO 8601解析为公历日期。 If I use the ParseTime class, I can only pass in the string format, and not the calendar for which the string is a representation of a date. 如果我使用ParseTime类,我只能传递字符串格式,而不能传递字符串作为日期表示的日历。 So, effectively, I'd pass in '20140502' and the ParseTime class would treat that string as the string representation of a modified Julian date. 所以,实际上,我传入'20140502',ParseTime类将该字符串视为修改后的Julian日期的字符串表示。

It seems like this ought to be a solved problem. 看起来这应该是一个解决的问题。 Ideally, I'd like a solution that does not use date-times. 理想情况下,我想要一个不使用日期时间的解决方案。 My model uses Gregorian calendar dates because that is all I need, and those are the things I will be comparing, searching, etc. 我的模型使用格里高利历日期,因为这就是我所需要的,那些是我将要比较,搜索等的东西。

Of course, the whole reason for using calendar days when I only need calendar days was so that I wouldn't have to think about how to compare and convert them, but I suppose that is a whine for another day. 当然,当我只需要日历日时使用日历日的全部原因是我不必考虑如何比较和转换它们,但我想这是另一天的抱怨。

Addendum: 附录:

Days are defined as: 天被定义为:

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

This lead me to believe that a Day is not a physical day, but a day in the MJD calendar (under the principle that the exposed documentation should tell us what a type represents, not the representation for the type). 这让我相信一天不是一个实际的日子,而是MJD日历中的一天(根据暴露的文档应该告诉我们类型代表什么的原则,而不是类型的表示)。

The GHC.Generics module is making this type of problem very easy to solve. 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

Though on reading your comment: 虽然在阅读你的评论:

The thing I'm after is a bugless way to parse an ISO 8601 date into a 'Day', which uses the modified Julian calendar. 我所追求的是将ISO 8601日期解析为'Day'的无法解决方法,该日期使用修改后的Julian日历。

This may not be the solution you are looking for. 这可能不是您正在寻找的解决方案。

Why doesn't parseTime do exactly what you want? 为什么parseTime没有做到你想要的呢? parseTime defaultTimeLocale "%F" is exactly the inverse (up to Just ) of showGregorian , as demonstrated by the following snippet that you can paste into GHCi. parseTime defaultTimeLocale "%F"恰好是showGregorian的反转(直到Just ),如下面的代码片段所示,您可以将其粘贴到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]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM