簡體   English   中英

使用Haskell /木薯將UTCTime轉換為CSV字段

[英]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 所以我的問題是:

  1. 錯誤與時間格式字符串有關嗎?如果是,為什么常規字符串不起作用?
  2. 這是使用cassava格式化要寫入CSV文件的日期類型的正確方法嗎?

您的問題是toField具有簽名toField a -> Field 如果查看Field類型,則其定義為type Field = ByteString formatTime的結果是String 因此,問題在於您提供了一個需要ByteStringString

由於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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM