这是一些旧代码,其中包含两种类型的自制日期,只有 YMD 的日期,没有时间或时区等。
它展示了如何使用readDec 将字符串解析为日期。请参阅parseDate 函数。使用readDec,读取数字,前导空格(因为filter)或前导零无关紧要,并且解析在第一个非数字处停止。然后使用tail(跳过非数字)进入日期的下一个数字字段。
它显示了几种格式化输出的方式,但最灵活的方式是使用Text.printf。见instance Show LtDate。有了 printf,一切皆有可能!
import Char
import Numeric
import Data.Time.Calendar
import Data.Time.Clock
import Text.Printf
-- ================================================================
-- LtDate
-- ================================================================
type Date=(Int,Int,Int)
data LtDate = LtDate
{ ltYear :: Int,
ltMonth:: Int,
ltDay :: Int
}
instance Show LtDate
where show d = printf "%4d-%02d-%02d" (ltYear d) (ltMonth d) (ltDay d)
toLtDate :: Date -> LtDate
toLtDate (y,m,d)= LtDate y m d
-- =============================================================
-- Date
-- =============================================================
-- | Parse a String mm/dd/yy into tuple (y,m,d)
-- accepted formats
--
-- @
-- 12\/01\/2004
-- 12\/ 1\' 4
-- 12-01-99
-- @
parseDate :: String -> Date
parseDate s = (y,m,d)
where [(m,rest) ] = readDec (filter (not . isSpace) s)
[(d,rest1)] = readDec (tail rest)
[(y, _) ] = parseDate' rest1
-- | parse the various year formats used by Quicken dates
parseDate':: String -> [(Int,String)]
parseDate' (y:ys) =
let [(iy,rest)] = readDec ys
year=case y of '\'' -> iy + 2000
_ ->
if iy < 1900 then iy + 1900 else iy
in [(year,rest)]
-- | Note some functions sort by this format
-- | So be careful when changing it.
showDate::(Int, Int, Int) -> String
showDate (y,m,d)= yy ++ '-':mm ++ '-':dd
where dd=zpad (show d)
mm = zpad (show m)
yy = show y
zpad ds@(_:ds')
| ds'==[] = '0':ds
| otherwise = ds
-- | from LtDate to Date
fromLtDate :: LtDate -> Date
fromLtDate lt = (ltYear lt, ltMonth lt, ltDay lt)
一旦有了 (Y,M,D),就很容易转换为 Haskell 库类型以进行数据操作。完成 HS 库后,Text.printf 可用于格式化显示日期。