[英]Convert UTCTime to CSV field with Haskell/cassava
我开始学习Haskell,并尝试从SQLite文件中查询数据并将其再次转储为CSV。 我在格式化UTCTime
字段时遇到问题,因此cassava
可以正确格式化它。 这是我的类型:
module History.Types
(Visit)
where
import Data.ByteString as B
import Data.Csv
import Data.Text (Text)
import Data.Time
import Data.Time.Format
import Database.SQLite.Simple.FromRow
data Visit = Visit
{ url :: Text
, title :: Text
, visit_count :: Int
, typed_count :: Int
, last_visit_time :: UTCTime
, visit_time :: UTCTime
, from_visit :: Int
}
deriving (Show)
instance FromRow Visit where
fromRow = Visit <$> field
<*> field
<*> field
<*> field
<*> field
<*> field
<*> field
instance ToField UTCTime where
toField t = formatTime defaultTimeLocale "%d-%m-%Y %H:%M:%S" t
instance ToRecord Visit where
toRecord (Visit url
title
visit_count
typed_count
last_visit_time
visit_time
from_visit) = record [ toField visit_time
, toField url
, toField title
, toField visit_count
, toField typed_count
, toField from_visit
, toField last_visit_time
]
和我的SQLite代码:
{-# LANGUAGE OverloadedStrings #-}
module History.DB
(queryHistory)
where
import History.Types (Visit)
import Data.Text (Text)
import Database.SQLite.Simple (open, query_, close, Query)
q :: Query
q = "\
\SELECT urls.url \
\ , urls.title \
\ , urls.visit_count \
\ , urls.typed_count \
\ , datetime(urls.last_visit_time/1000000-11644473600,'unixepoch','localtime') \
\ , datetime(visits.visit_time/1000000-11644473600,'unixepoch','localtime') \
\ , visits.from_visit \
\FROM urls, visits \
\WHERE urls.id = visits.id \
\ORDER BY visits.visit_time"
queryHistory :: FilePath -> IO [Visit]
queryHistory dbPath =
do conn <- open dbPath
history <- query_ conn q
close conn
return history
编译此代码会导致以下错误:
src/History/Types.hs:34:15:
Couldn't match type ‘[Char]’ with ‘ByteString’
Expected type: Field
Actual type: String
In the expression:
formatTime defaultTimeLocale "%d-%m-%Y %H:%M:%S" t
In an equation for ‘toField’:
toField t = formatTime defaultTimeLocale "%d-%m-%Y %H:%M:%S" t
所以很显然,当将日期类型格式化为字符串时,我会感到一团糟。 我查看formatTime
的类型信息, formatTime
并不太了解为什么我的String
(我认为错误与日期格式字符串有关)必须是ByteString
。 所以我的问题是:
cassava
格式化要写入CSV文件的日期类型的正确方法吗? 您的问题是toField
具有签名toField
a -> Field
。 如果查看Field
类型,则其定义为type Field = ByteString
。 formatTime
的结果是String
。 因此,问题在于您提供了一个需要ByteString
的String
。
由于String
是非常常见的类型,因此您应该做的第一件事是检查是否已经可以使用ToField String
的实例。 如果您看一下定义 ,就会发现。 这意味着您可以专门使toField
函数具有签名toField
String -> Field
并像这样使用它:
instance ToField UTCTime where
toField = toField . formatTime defaultTimeLocale "%d-%m-%Y %H:%M:%S"
您是否在History.Types文件中尝试过{-#LANGUAGE OverloadedStrings#-}? 不知道这是否行得通,但也许值得一试。
ToField必须返回一个ByteString,因为它返回一个Field,而一个Field是一个ByteString:
http://haddock.stackage.org/lts-2.17/cassava-0.4.3.0/Data-Csv.html#t:Field
您正在正确地调用formatTime,只是formatTime返回一个String而不是一个ByteString。
您可以直接使用fromString或pack进行转换。 因此,像现在一样调用formatTime并转换结果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.