[英]Convert UTCTime to CSV field with Haskell/cassava
I started learning Haskell and I try to query data from a SQLite file and dump it again as CSV. 我开始学习Haskell,并尝试从SQLite文件中查询数据并将其再次转储为CSV。 I have an issue formating
UTCTime
fields, so that cassava
can format it correctly. 我在格式化
UTCTime
字段时遇到问题,因此cassava
可以正确格式化它。 This is my type: 这是我的类型:
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
]
And my SQLite code: 和我的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
Compiling this code leads to the following error: 编译此代码会导致以下错误:
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
So clearly I make a mess with when formatting the date type into a string. 所以很显然,当将日期类型格式化为字符串时,我会感到一团糟。 I look at the type information of
formatTime
and don't really understand why my String
(I assume the error relates to the date formatting string) has to be a ByteString
. 我查看
formatTime
的类型信息, formatTime
并不太了解为什么我的String
(我认为错误与日期格式字符串有关)必须是ByteString
。 So my questions are: 所以我的问题是:
cassava
? cassava
格式化要写入CSV文件的日期类型的正确方法吗? Your problem is that toField
has the signature a -> Field
. 您的问题是
toField
具有签名toField
a -> Field
。 If you look at the Field
type its definition is type Field = ByteString
. 如果查看
Field
类型,则其定义为type Field = ByteString
。 The result of formatTime
is a String
. formatTime
的结果是String
。 So the problem is that you provide a String
where a ByteString
is expected. 因此,问题在于您提供了一个需要
ByteString
的String
。
Since String
is a very common type the first thing you should do is to check if there is already an instance for ToField String
you can use. 由于
String
是非常常见的类型,因此您应该做的第一件事是检查是否已经可以使用ToField String
的实例。 If you look at the definition there is. 如果您看一下定义 ,就会发现。 This means that you can specialize the
toField
function to have the signature String -> Field
and the use it like this: 这意味着您可以专门使
toField
函数具有签名toField
String -> Field
并像这样使用它:
instance ToField UTCTime where
toField = toField . formatTime defaultTimeLocale "%d-%m-%Y %H:%M:%S"
Have you tried {-# LANGUAGE OverloadedStrings #-} in your History.Types file? 您是否在History.Types文件中尝试过{-#LANGUAGE OverloadedStrings#-}? Not sure if that would work, but maybe worth a try.
不知道这是否行得通,但也许值得一试。
ToField has to return a ByteString because it returns a Field, and a Field IS a ByteString: ToField必须返回一个ByteString,因为它返回一个Field,而一个Field是一个ByteString:
http://haddock.stackage.org/lts-2.17/cassava-0.4.3.0/Data-Csv.html#t:Field http://haddock.stackage.org/lts-2.17/cassava-0.4.3.0/Data-Csv.html#t:Field
You are calling formatTime correctly, its just that formatTime returns a String and not a ByteString. 您正在正确地调用formatTime,只是formatTime返回一个String而不是一个ByteString。
You can directly convert with fromString or pack . 您可以直接使用fromString或pack进行转换。 So just call formatTime like you are now and convert the result.
因此,像现在一样调用formatTime并转换结果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.