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 | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										16
									
								
								Options.hs
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								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  | ||||||
|  | |||||||
							
								
								
									
										10
									
								
								hledger.hs
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								hledger.hs
									
									
									
									
									
								
							| @ -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 | ||||||
|     ledgerFilePathFromOpts opts >>= parseLedgerFile >>= either printParseError runcmd |   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 | ||||||
|     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