tighten up date parsing, make it io-friendly and parse Y, M/D, D
This commit is contained in:
parent
b3c0bba51e
commit
1c60514973
@ -500,10 +500,14 @@ smartdate = do
|
|||||||
(y,m,d) <- (
|
(y,m,d) <- (
|
||||||
try ymd
|
try ymd
|
||||||
<|> try ym
|
<|> try ym
|
||||||
|
<|> try md
|
||||||
<|> try y
|
<|> try y
|
||||||
-- <|> try md
|
<|> try d
|
||||||
-- <|> try month
|
-- <|> try month
|
||||||
-- <|> try mon
|
-- <|> try mon
|
||||||
|
-- <|> try today
|
||||||
|
-- <|> try yesterday
|
||||||
|
-- <|> try tomorrow
|
||||||
-- <|> try thiswhatever
|
-- <|> try thiswhatever
|
||||||
-- <|> try nextwhatever
|
-- <|> try nextwhatever
|
||||||
-- <|> try lastwhatever
|
-- <|> try lastwhatever
|
||||||
@ -517,27 +521,54 @@ ymd = do
|
|||||||
y <- many digit
|
y <- many digit
|
||||||
datesep
|
datesep
|
||||||
m <- many digit
|
m <- many digit
|
||||||
|
guard (read m <= 12)
|
||||||
datesep
|
datesep
|
||||||
d <- many digit
|
d <- many digit
|
||||||
|
guard (read d <= 31)
|
||||||
return (y,m,d)
|
return (y,m,d)
|
||||||
|
|
||||||
ym :: Parser (String,String,String)
|
ym :: Parser (String,String,String)
|
||||||
ym = do
|
ym = do
|
||||||
y <- many digit
|
y <- many digit
|
||||||
|
guard (read y > 12)
|
||||||
datesep
|
datesep
|
||||||
m <- many digit
|
m <- many digit
|
||||||
|
guard (read m <= 12)
|
||||||
return (y,m,"1")
|
return (y,m,"1")
|
||||||
|
|
||||||
y :: Parser (String,String,String)
|
y :: Parser (String,String,String)
|
||||||
y = do
|
y = do
|
||||||
y <- many digit
|
y <- many digit
|
||||||
|
guard (read y >= 1000)
|
||||||
return (y,"1","1")
|
return (y,"1","1")
|
||||||
|
|
||||||
-- | Parse a flexible date string, with awareness of the current time,
|
d :: Parser (String,String,String)
|
||||||
-- and return a Date or raise an error.
|
d = do
|
||||||
smartparsedate :: String -> Date
|
d <- many digit
|
||||||
smartparsedate s = parsedate $ printf "%04s/%02s/%02s" y m d
|
guard (read d <= 31)
|
||||||
where (y,m,d) = fromparse $ parsewith smartdate s
|
return ("","",d)
|
||||||
|
|
||||||
|
-- | Parse a M/D string as ("",M,D), year will be filled in later
|
||||||
|
md :: Parser (String,String,String)
|
||||||
|
md = do
|
||||||
|
m <- many digit
|
||||||
|
guard (read m <= 12)
|
||||||
|
datesep
|
||||||
|
d <- many digit
|
||||||
|
guard (read d <= 31)
|
||||||
|
return ("",m,d)
|
||||||
|
|
||||||
|
-- | Parse a flexible date string to a Date with awareness of the current
|
||||||
|
-- time, or raise an error.
|
||||||
|
smartparsedate :: String -> IO Date
|
||||||
|
smartparsedate s = do
|
||||||
|
let (y,m,d) = fromparse $ parsewith smartdate s
|
||||||
|
(thisy,thism,_) <- today >>= return . dateComponents
|
||||||
|
let (y',m',d') = case (y,m,d) of
|
||||||
|
("","",d) -> (show thisy,show thism,d)
|
||||||
|
("",m,d) -> (show thisy,m,d)
|
||||||
|
otherwise -> (y,m,d)
|
||||||
|
return $ parsedate $ printf "%04s/%02s/%02s" y' m' d'
|
||||||
|
|
||||||
type TransactionMatcher = Transaction -> Bool
|
type TransactionMatcher = Transaction -> Bool
|
||||||
|
|
||||||
|
|||||||
14
Options.hs
14
Options.hs
@ -113,11 +113,11 @@ tildeExpand ('~':'/':xs) = getHomeDirectory >>= return . (++ ('/':xs))
|
|||||||
tildeExpand xs = return xs
|
tildeExpand xs = return xs
|
||||||
|
|
||||||
-- | Get the value of the begin date option, if any.
|
-- | Get the value of the begin date option, if any.
|
||||||
beginDateFromOpts :: [Opt] -> Maybe Date
|
beginDateFromOpts :: [Opt] -> IO (Maybe Date)
|
||||||
beginDateFromOpts opts =
|
beginDateFromOpts opts =
|
||||||
case beginopts of
|
case beginopts of
|
||||||
(x:_) -> Just $ smartparsedate $ last beginopts
|
(x:_) -> smartparsedate (last beginopts) >>= return . Just
|
||||||
_ -> Nothing
|
_ -> return Nothing
|
||||||
where
|
where
|
||||||
beginopts = concatMap getbegindate opts
|
beginopts = concatMap getbegindate opts
|
||||||
getbegindate (Begin s) = [s]
|
getbegindate (Begin s) = [s]
|
||||||
@ -125,11 +125,11 @@ beginDateFromOpts opts =
|
|||||||
defaultdate = ""
|
defaultdate = ""
|
||||||
|
|
||||||
-- | Get the value of the end date option, if any.
|
-- | Get the value of the end date option, if any.
|
||||||
endDateFromOpts :: [Opt] -> Maybe Date
|
endDateFromOpts :: [Opt] -> IO (Maybe Date)
|
||||||
endDateFromOpts opts =
|
endDateFromOpts opts = do
|
||||||
case endopts of
|
case endopts of
|
||||||
(x:_) -> Just $ smartparsedate $ last endopts
|
(x:_) -> smartparsedate (last endopts) >>= return . Just
|
||||||
_ -> Nothing
|
_ -> return Nothing
|
||||||
where
|
where
|
||||||
endopts = concatMap getenddate opts
|
endopts = concatMap getenddate opts
|
||||||
getenddate (End s) = [s]
|
getenddate (End s) = [s]
|
||||||
|
|||||||
12
Tests.hs
12
Tests.hs
@ -98,9 +98,15 @@ misc_tests = TestList [
|
|||||||
assertparseequal timelog1 (parsewith timelog timelog1_str)
|
assertparseequal timelog1 (parsewith timelog timelog1_str)
|
||||||
,
|
,
|
||||||
"smartparsedate" ~: do
|
"smartparsedate" ~: do
|
||||||
assertequal (1999,12,13) (dateComponents $ smartparsedate "1999/12/13")
|
(thisyear,thismonth,thisday) <- today >>= return . dateComponents
|
||||||
assertequal (2008,2,1) (dateComponents $ smartparsedate "2008-2")
|
d <- smartparsedate "1999-12-02"; assertequal (1999,12,2) (dateComponents d)
|
||||||
assertequal (2008,1,1) (dateComponents $ smartparsedate "2008")
|
d <- smartparsedate "1999.12.02"; assertequal (1999,12,2) (dateComponents d)
|
||||||
|
d <- smartparsedate "1999/3/2"; assertequal (1999,3,2) (dateComponents d)
|
||||||
|
d <- smartparsedate "2008/2"; assertequal (2008,2,1) (dateComponents d)
|
||||||
|
d <- smartparsedate "20/2"; assertequal (20,2,1) (dateComponents d)
|
||||||
|
d <- smartparsedate "4/2"; assertequal (thisyear,4,2) (dateComponents d)
|
||||||
|
d <- smartparsedate "1000"; assertequal (1000,1,1) (dateComponents d)
|
||||||
|
d <- smartparsedate "2"; assertequal (thisyear,thismonth,2) (dateComponents d)
|
||||||
]
|
]
|
||||||
|
|
||||||
balancereportacctnames_tests = TestList
|
balancereportacctnames_tests = TestList
|
||||||
|
|||||||
@ -68,12 +68,12 @@ main = do
|
|||||||
-- | parse the user's specified ledger file and do some action with it
|
-- | parse the user's specified ledger file and do some action with it
|
||||||
-- (or report a parse error). This function makes the whole thing go.
|
-- (or report a parse error). This function makes the whole thing go.
|
||||||
parseLedgerAndDo :: [Opt] -> [String] -> ([Opt] -> [String] -> Ledger -> IO ()) -> IO ()
|
parseLedgerAndDo :: [Opt] -> [String] -> ([Opt] -> [String] -> Ledger -> IO ()) -> IO ()
|
||||||
parseLedgerAndDo opts args cmd =
|
parseLedgerAndDo opts args cmd = do
|
||||||
|
b <- beginDateFromOpts opts
|
||||||
|
e <- endDateFromOpts opts
|
||||||
|
let runcmd = cmd opts args . cacheLedger apats . filterRawLedger b e dpats c r . canonicaliseAmounts costbasis
|
||||||
ledgerFilePathFromOpts opts >>= parseLedgerFile >>= either printParseError runcmd
|
ledgerFilePathFromOpts opts >>= parseLedgerFile >>= either printParseError runcmd
|
||||||
where
|
where
|
||||||
runcmd = cmd opts args . cacheLedger apats . filterRawLedger b e dpats c r . canonicaliseAmounts costbasis
|
|
||||||
b = beginDateFromOpts opts
|
|
||||||
e = endDateFromOpts opts
|
|
||||||
(apats,dpats) = parseAccountDescriptionArgs opts args
|
(apats,dpats) = parseAccountDescriptionArgs opts args
|
||||||
c = Cleared `elem` opts
|
c = Cleared `elem` opts
|
||||||
r = Real `elem` opts
|
r = Real `elem` opts
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user