我试图用这样的数据解析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)
答案 0 :(得分:2)
您正在使用show
,它将值包装在双引号中。 parseTimeM
正在接收值"\"2001/12/18\""
,并且它不知道期望字符串开头和结尾的引号。删除那些引号,你应该没事。
答案 1 :(得分:0)
这个问题很老了,但我刚刚自己解决了,所以让我把它贴在这里。
根据手册,parseField
是一个函数类型:
parseField :: Field -> Parser a
在我们的例子中,我们希望类型 a
为 Day
,而 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