用木薯解析csv的日期

时间:2016-02-14 20:17:34

标签: haskell

我试图用这样的数据解析csv文件。我可以用日期作为字符串进行解析,但是还没有能够以日期格式获取它们。我终于得到了这个类型检查,但现在我有一个解析错误,希望得到一些帮助。

2001/12/18, 281
2001/12/19, 280
2001/12/20, 276
2001/12/21, 278

到目前为止,这是我的代码。

{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}

import qualified Data.ByteString.Lazy as BL
import Data.Csv
import qualified Data.Vector as V
import Data.Time
import Generics.Deriving

datadir="/home/john/.stack/test/data/"  

data Sample = Sample { dateMeasure :: !Data.Time.Day 
                 , valueMeasure :: !Int 
                 } deriving (Generic, Show)   

instance FromRecord Sample 

instance FromField Data.Time.Day where
    parseField = parseTimeM True defaultTimeLocale "%Y/%m/%d" . show 

printRecord :: Sample -> IO ()
printRecord r  = putStrLn $  show (dateMeasure r) ++ " measurement is " ++    show (valueMeasure r) 

main :: IO ()
main = do
    csvData <- BL.readFile $ datadir ++ "sample.csv"
    case decode NoHeader csvData :: Either String (V.Vector Sample) of
        Left err -> putStrLn err
        Right v -> V.forM_ v $ printRecord   

这是我得到的错误

~/.stack/test/ stack exec test
parse error (Failed reading: conversion error: parseTimeM: no parse of "\"2001/12/18\"") at 
2001/12/19, 280
2001/12/20, 276
2001/12/21, 278
2001/12/26, 278
2001/12/27, 278
2001/12/28, 2 (truncated)

2 个答案:

答案 0 :(得分:2)

您正在使用show,它将值包装在双引号中。 parseTimeM正在接收值"\"2001/12/18\"",并且它不知道期望字符串开头和结尾的引号。删除那些引号,你应该没事。

答案 1 :(得分:0)

这个问题很老了,但我刚刚自己解决了,所以让我把它贴在这里。

根据手册,parseField 是一个函数类型:

parseField :: Field -> Parser a 

在我们的例子中,我们希望类型 aDay,而 Field 只是一个类型别名

type Field = ByteString

您使用的功能:

parseTimeM True defaultTimeLocale "%Y/%m/%d"

需要 String,而不是 ByteString。因此,为了使一切正确,您需要提供一个适配器函数 ByteString -> String

使用 show 可以让所有类型检查,但它有一个缺陷,它在结果字符串中留下引号。 更好的选择是使用 unpack 函数来执行类型之间的转换。

所以整个代码是:

import Data.ByteString.Char8 (unpack)

instance FromField Data.Time.Day where
    parseField = parseTimeM True defaultTimeLocale "%Y/%m/%d" . unpack