mirror of
https://github.com/simonmichael/hledger.git
synced 2024-12-26 03:42:25 +03:00
lib: datep now requires years to be at least four digits.
This commit is contained in:
parent
ffb5cf0773
commit
dc41cee2b0
@ -12,20 +12,20 @@ Some of these might belong in Hledger.Read.JournalReader or Hledger.Read.
|
|||||||
-}
|
-}
|
||||||
|
|
||||||
--- ** language
|
--- ** language
|
||||||
{-# LANGUAGE BangPatterns #-}
|
{-# LANGUAGE BangPatterns #-}
|
||||||
{-# LANGUAGE CPP #-}
|
{-# LANGUAGE CPP #-}
|
||||||
{-# LANGUAGE DeriveDataTypeable #-}
|
{-# LANGUAGE DeriveDataTypeable #-}
|
||||||
{-# LANGUAGE FlexibleContexts #-}
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
{-# LANGUAGE LambdaCase #-}
|
{-# LANGUAGE LambdaCase #-}
|
||||||
{-# LANGUAGE NamedFieldPuns #-}
|
{-# LANGUAGE NamedFieldPuns #-}
|
||||||
{-# LANGUAGE NoMonoLocalBinds #-}
|
{-# LANGUAGE NoMonoLocalBinds #-}
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE PackageImports #-}
|
{-# LANGUAGE PackageImports #-}
|
||||||
{-# LANGUAGE Rank2Types #-}
|
{-# LANGUAGE Rank2Types #-}
|
||||||
{-# LANGUAGE RecordWildCards #-}
|
{-# LANGUAGE RecordWildCards #-}
|
||||||
{-# LANGUAGE ScopedTypeVariables #-}
|
{-# LANGUAGE ScopedTypeVariables #-}
|
||||||
{-# LANGUAGE TupleSections #-}
|
{-# LANGUAGE TupleSections #-}
|
||||||
{-# LANGUAGE TypeFamilies #-}
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
|
|
||||||
--- ** exports
|
--- ** exports
|
||||||
module Hledger.Read.Common (
|
module Hledger.Read.Common (
|
||||||
@ -446,45 +446,44 @@ datep = do
|
|||||||
|
|
||||||
datep' :: Maybe Year -> TextParser m Day
|
datep' :: Maybe Year -> TextParser m Day
|
||||||
datep' mYear = do
|
datep' mYear = do
|
||||||
startOffset <- getOffset
|
startOffset <- getOffset
|
||||||
d1 <- decimal <?> "year or month"
|
d1 <- yearorintp <?> "year or month"
|
||||||
sep <- satisfy isDateSepChar <?> "date separator"
|
sep <- datesepchar <?> "date separator"
|
||||||
d2 <- decimal <?> "month or day"
|
d2 <- decimal <?> "month or day"
|
||||||
fullDate startOffset d1 sep d2 <|> partialDate startOffset mYear d1 sep d2
|
case d1 of
|
||||||
<?> "full or partial date"
|
Left y -> fullDate startOffset y sep d2
|
||||||
|
Right m -> partialDate startOffset mYear m sep d2
|
||||||
|
<?> "full or partial date"
|
||||||
where
|
where
|
||||||
|
fullDate :: Int -> Year -> Char -> Month -> TextParser m Day
|
||||||
|
fullDate startOffset year sep1 month = do
|
||||||
|
sep2 <- satisfy isDateSepChar <?> "date separator"
|
||||||
|
day <- decimal <?> "day"
|
||||||
|
endOffset <- getOffset
|
||||||
|
let dateStr = show year ++ [sep1] ++ show month ++ [sep2] ++ show day
|
||||||
|
|
||||||
fullDate :: Int -> Integer -> Char -> Int -> TextParser m Day
|
when (sep1 /= sep2) $ customFailure $ parseErrorAtRegion startOffset endOffset $
|
||||||
fullDate startOffset year sep1 month = do
|
"invalid date (mixing date separators is not allowed): " ++ dateStr
|
||||||
sep2 <- satisfy isDateSepChar <?> "date separator"
|
|
||||||
day <- decimal <?> "day"
|
|
||||||
endOffset <- getOffset
|
|
||||||
let dateStr = show year ++ [sep1] ++ show month ++ [sep2] ++ show day
|
|
||||||
|
|
||||||
when (sep1 /= sep2) $ customFailure $ parseErrorAtRegion startOffset endOffset $
|
case fromGregorianValid year month day of
|
||||||
"invalid date (mixing date separators is not allowed): " ++ dateStr
|
Nothing -> customFailure $ parseErrorAtRegion startOffset endOffset $
|
||||||
|
"well-formed but invalid date: " ++ dateStr
|
||||||
|
Just date -> pure $! date
|
||||||
|
|
||||||
case fromGregorianValid year month day of
|
partialDate :: Int -> Maybe Year -> Month -> Char -> MonthDay -> TextParser m Day
|
||||||
Nothing -> customFailure $ parseErrorAtRegion startOffset endOffset $
|
partialDate startOffset mYear month sep day = do
|
||||||
"well-formed but invalid date: " ++ dateStr
|
endOffset <- getOffset
|
||||||
Just date -> pure $! date
|
case mYear of
|
||||||
|
Just year ->
|
||||||
|
case fromGregorianValid year month day of
|
||||||
|
Nothing -> customFailure $ parseErrorAtRegion startOffset endOffset $
|
||||||
|
"well-formed but invalid date: " ++ dateStr
|
||||||
|
Just date -> pure $! date
|
||||||
|
where dateStr = show year ++ [sep] ++ show month ++ [sep] ++ show day
|
||||||
|
|
||||||
partialDate
|
Nothing -> customFailure $ parseErrorAtRegion startOffset endOffset $
|
||||||
:: Int -> Maybe Year -> Integer -> Char -> Int -> TextParser m Day
|
"partial date "++dateStr++" found, but the current year is unknown"
|
||||||
partialDate startOffset mYear month sep day = do
|
where dateStr = show month ++ [sep] ++ show day
|
||||||
endOffset <- getOffset
|
|
||||||
case mYear of
|
|
||||||
Just year ->
|
|
||||||
case fromGregorianValid year (fromIntegral month) day of
|
|
||||||
Nothing -> customFailure $ parseErrorAtRegion startOffset endOffset $
|
|
||||||
"well-formed but invalid date: " ++ dateStr
|
|
||||||
Just date -> pure $! date
|
|
||||||
where dateStr = show year ++ [sep] ++ show month ++ [sep] ++ show day
|
|
||||||
|
|
||||||
Nothing -> customFailure $ parseErrorAtRegion startOffset endOffset $
|
|
||||||
"partial date "++dateStr++" found, but the current year is unknown"
|
|
||||||
where dateStr = show month ++ [sep] ++ show day
|
|
||||||
|
|
||||||
{-# INLINABLE datep' #-}
|
{-# INLINABLE datep' #-}
|
||||||
|
|
||||||
@ -551,6 +550,14 @@ secondarydatep :: Day -> TextParser m Day
|
|||||||
secondarydatep primaryDate = char '=' *> datep' (Just primaryYear)
|
secondarydatep primaryDate = char '=' *> datep' (Just primaryYear)
|
||||||
where primaryYear = first3 $ toGregorian primaryDate
|
where primaryYear = first3 $ toGregorian primaryDate
|
||||||
|
|
||||||
|
-- | Parse a year number or an Int. Years must contain at least four
|
||||||
|
-- digits.
|
||||||
|
yearorintp :: TextParser m (Either Year Int)
|
||||||
|
yearorintp = do
|
||||||
|
yearOrMonth <- takeWhile1P (Just "digit") isDigit
|
||||||
|
let n = readDecimal yearOrMonth
|
||||||
|
return $ if T.length yearOrMonth >= 4 then Left n else Right (fromInteger n)
|
||||||
|
|
||||||
--- *** account names
|
--- *** account names
|
||||||
|
|
||||||
-- | Parse an account name (plus one following space if present),
|
-- | Parse an account name (plus one following space if present),
|
||||||
|
@ -50,5 +50,5 @@ end comment
|
|||||||
2000/1/2
|
2000/1/2
|
||||||
b 0 ; [1/1=1/2/3/4] bad second date, should error
|
b 0 ; [1/1=1/2/3/4] bad second date, should error
|
||||||
|
|
||||||
>>>2 /9:23/
|
>>>2 /-:9:21/
|
||||||
>>>=1
|
>>>=1
|
||||||
|
Loading…
Reference in New Issue
Block a user