[英]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.