在Haskell中解析多种日期格式

时间:2014-06-08 08:19:00

标签: parsing date haskell

我正在尝试使用Haskell来处理我想要分析的一些数据。这些数据主要是结构化的,但不一致。日期可能有许多表示形式,但总是在相同的位置(文档是XML)。

到目前为止我看到的不同格式是:

“1971年2月25日”

“星期四。6月22日。1972年。”

“7月3日。1973年。”

“10月17日星期四\ r \ n 1974年。”

“1976年3月5日星期五。”

“4月25日\ r \ n 1977.”

“1983年12月6日星期二”

“1988年5月10日”

“1988年10月20日”

我真的不知道从哪里开始 - 我可以处理的任何个别格式,但我不知道如何处理所有这些格式。我想要一个函数String - >也许是Day。

2 个答案:

答案 0 :(得分:1)

首先解决每个问题,并将自己局限于其中一个解析器。 首先为这个解析器编写一些测试。

在Haskell中解析与在其他语言中解析完全不同,通常使用正则表达式或其他方法。在haskell中,我们拥有提供解析器组合的优秀库。我使用的是parsecattoparsec

  • 为每个数据类型创建数据类型或使用现有的time - 包。

  • 为每个月(JanFeb ...)编写一个解析器,然后将它们组合起来。 但请注意,MarchMay都以相同的字母开头 你需要的不仅仅是简单的组合。 JanuaryJuneJuly

  • 也是如此
  • 对于简单的解析器(对于正面和负面的情况)再次进行一些测试是非常有帮助的。
  • 为每一天(第1或第2或第3或第n)编写解析器
  • 再次将它们结合起来要小心 - 第11和第12次同时开始使用' 1'
  • 多年来编写解析器

现在你应该有Parser DayParser MonthParser Year,甚至可能Parser Weekday

  • 将这些解析器组合在一起形成您自己限制的解析器,以获得Parser Day
  • 现在你应该有足够的实用工具来实现其余的工作

最后一点,有很多parsec / attoparsec的教程,只是使用你最不信任的搜索引擎。

答案 1 :(得分:1)

hackage上有几个用于解析日期的库:

然后你可以将几个这样的解析器链接在一起。这是一个手动“替代”运算符:

    -- Chain operator: if p1 returns Nothing, then return p2
    p1 <||> p2 = case p1 of
                   Nothing -> p2
                   Just r -> Just r

所以你要为每种格式编写一个解析函数:

    p1 :: String -> Maybe Day

然后将这些结合起来:

    parseDate :: String -> Maybe Day
    parseDate = p1 <||> p2 <||> p3

如果您编写了正确的Parser,则可以从<|>免费获得此替代运算符(Control.Applicative)。这是编写自己的解析器的tutorial

我还建议通过消除标点符号甚至“rd”格式来预处理原始文本,以使其更加健壮并减少您必须编写的解析函数的数量。如果您需要更好的性能,也请考虑使用Data.Text