parsing: historical price directives may contain a numeric time zone, like ledger; note that the time is ignored
This commit is contained in:
parent
946e5ffcbc
commit
8d62452260
@ -290,6 +290,8 @@ historical price directive (P) as shown:
|
|||||||
expenses:foreign currency €100
|
expenses:foreign currency €100
|
||||||
assets
|
assets
|
||||||
|
|
||||||
|
Note: a time and numeric time zone are allowed in historical price directives, but currently ignored.
|
||||||
|
|
||||||
Or, you can write a transaction in two commodities, without prices but
|
Or, you can write a transaction in two commodities, without prices but
|
||||||
with all amounts specified, and a conversion price will be inferred so as
|
with all amounts specified, and a conversion price will be inferred so as
|
||||||
to balance the transaction:
|
to balance the transaction:
|
||||||
|
|||||||
@ -123,8 +123,11 @@ import Data.List
|
|||||||
import Data.List.Split (wordsBy)
|
import Data.List.Split (wordsBy)
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import Data.Time.Calendar
|
import Data.Time.Calendar
|
||||||
|
-- import Data.Time.Clock
|
||||||
|
-- import Data.Time.Format
|
||||||
import Data.Time.LocalTime
|
import Data.Time.LocalTime
|
||||||
import Safe (headDef)
|
import Safe (headDef)
|
||||||
|
-- import System.Locale (defaultTimeLocale)
|
||||||
import Test.HUnit
|
import Test.HUnit
|
||||||
import Text.ParserCombinators.Parsec hiding (parse)
|
import Text.ParserCombinators.Parsec hiding (parse)
|
||||||
import Text.Printf
|
import Text.Printf
|
||||||
@ -364,6 +367,8 @@ ledgerTransaction = do
|
|||||||
postings <- ledgerpostings
|
postings <- ledgerpostings
|
||||||
return $ txnTieKnot $ Transaction date edate status code description comment md postings ""
|
return $ txnTieKnot $ Transaction date edate status code description comment md postings ""
|
||||||
|
|
||||||
|
-- | Parse a date in YYYY/MM/DD format. Fewer digits are allowed. The year
|
||||||
|
-- may be omitted if a default year has already been set.
|
||||||
ledgerdate :: GenParser Char JournalContext Day
|
ledgerdate :: GenParser Char JournalContext Day
|
||||||
ledgerdate = do
|
ledgerdate = do
|
||||||
-- hacky: try to ensure precise errors for invalid dates
|
-- hacky: try to ensure precise errors for invalid dates
|
||||||
@ -383,6 +388,10 @@ ledgerdate = do
|
|||||||
Just date -> return date
|
Just date -> return date
|
||||||
<?> "full or partial date"
|
<?> "full or partial date"
|
||||||
|
|
||||||
|
-- | Parse a date and time in YYYY/MM/DD HH:MM[:SS][+-ZZZZ] format. Any
|
||||||
|
-- timezone will be ignored; the time is treated as local time. Fewer
|
||||||
|
-- digits are allowed, except in the timezone. The year may be omitted if
|
||||||
|
-- a default year has already been set.
|
||||||
ledgerdatetime :: GenParser Char JournalContext LocalTime
|
ledgerdatetime :: GenParser Char JournalContext LocalTime
|
||||||
ledgerdatetime = do
|
ledgerdatetime = do
|
||||||
day <- ledgerdate
|
day <- ledgerdate
|
||||||
@ -394,14 +403,22 @@ ledgerdatetime = do
|
|||||||
m <- many1 digit
|
m <- many1 digit
|
||||||
let m' = read m
|
let m' = read m
|
||||||
guard $ m' >= 0 && m' <= 59
|
guard $ m' >= 0 && m' <= 59
|
||||||
s <- optionMaybe $ do
|
s <- optionMaybe $ char ':' >> many1 digit
|
||||||
char ':'
|
|
||||||
many1 digit
|
|
||||||
let s' = case s of Just sstr -> read sstr
|
let s' = case s of Just sstr -> read sstr
|
||||||
Nothing -> 0
|
Nothing -> 0
|
||||||
guard $ s' >= 0 && s' <= 59
|
guard $ s' >= 0 && s' <= 59
|
||||||
let tod = TimeOfDay h' m' (fromIntegral s')
|
{- tz <- -}
|
||||||
return $ LocalTime day tod
|
optionMaybe $ do
|
||||||
|
plusminus <- oneOf "-+"
|
||||||
|
d1 <- digit
|
||||||
|
d2 <- digit
|
||||||
|
d3 <- digit
|
||||||
|
d4 <- digit
|
||||||
|
return $ plusminus:d1:d2:d3:d4:""
|
||||||
|
-- ltz <- liftIO $ getCurrentTimeZone
|
||||||
|
-- let tz' = maybe ltz (fromMaybe ltz . parseTime defaultTimeLocale "%z") tz
|
||||||
|
-- return $ localTimeToUTC tz' $ LocalTime day $ TimeOfDay h' m' (fromIntegral s')
|
||||||
|
return $ LocalTime day $ TimeOfDay h' m' (fromIntegral s')
|
||||||
|
|
||||||
ledgereffectivedate :: Day -> GenParser Char JournalContext Day
|
ledgereffectivedate :: Day -> GenParser Char JournalContext Day
|
||||||
ledgereffectivedate actualdate = do
|
ledgereffectivedate actualdate = do
|
||||||
@ -729,13 +746,20 @@ tests_Hledger_Read_JournalReader = TestList [
|
|||||||
assertParse (parseWithCtx nullctx{ctxYear=Just 2011} ledgerdate "1/1")
|
assertParse (parseWithCtx nullctx{ctxYear=Just 2011} ledgerdate "1/1")
|
||||||
|
|
||||||
,"ledgerdatetime" ~: do
|
,"ledgerdatetime" ~: do
|
||||||
assertParseFailure (parseWithCtx nullctx ledgerdatetime "2011/1/1")
|
let p = do {t <- ledgerdatetime; eof; return t}
|
||||||
assertParseFailure (parseWithCtx nullctx ledgerdatetime "2011/1/1 24:00:00")
|
bad = assertParseFailure . parseWithCtx nullctx p
|
||||||
assertParseFailure (parseWithCtx nullctx ledgerdatetime "2011/1/1 00:60:00")
|
good = assertParse . parseWithCtx nullctx p
|
||||||
assertParseFailure (parseWithCtx nullctx ledgerdatetime "2011/1/1 00:00:60")
|
bad "2011/1/1"
|
||||||
assertParse (parseWithCtx nullctx ledgerdatetime "2011/1/1 00:00")
|
bad "2011/1/1 24:00:00"
|
||||||
assertParse (parseWithCtx nullctx ledgerdatetime "2011/1/1 23:59:59")
|
bad "2011/1/1 00:60:00"
|
||||||
assertParse (parseWithCtx nullctx ledgerdatetime "2011/1/1 3:5:7")
|
bad "2011/1/1 00:00:60"
|
||||||
|
good "2011/1/1 00:00"
|
||||||
|
good "2011/1/1 23:59:59"
|
||||||
|
good "2011/1/1 3:5:7"
|
||||||
|
-- timezone is parsed but ignored
|
||||||
|
let startofday = LocalTime (fromGregorian 2011 1 1) (TimeOfDay 0 0 (fromIntegral 0))
|
||||||
|
assertParseEqual (parseWithCtx nullctx p "2011/1/1 00:00-0800") startofday
|
||||||
|
assertParseEqual (parseWithCtx nullctx p "2011/1/1 00:00+1234") startofday
|
||||||
|
|
||||||
,"ledgerDefaultYear" ~: do
|
,"ledgerDefaultYear" ~: do
|
||||||
assertParse (parseWithCtx nullctx ledgerDefaultYear "Y 2010\n")
|
assertParse (parseWithCtx nullctx ledgerDefaultYear "Y 2010\n")
|
||||||
|
|||||||
21
tests/timezone.test
Normal file
21
tests/timezone.test
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# timezone-related tests
|
||||||
|
# 1. as in ledger, historical prices may contain a time and timezone.
|
||||||
|
# hledger ignores them and uses 00:00 local time instead.
|
||||||
|
bin/hledger -f - balance --no-total --cost
|
||||||
|
<<<
|
||||||
|
P 2011/01/01 00:00:00 A $1
|
||||||
|
P 2011/01/01 15:00:00-0100 A $2
|
||||||
|
|
||||||
|
2010/12/31
|
||||||
|
(20101231) 1 A
|
||||||
|
|
||||||
|
2011/1/1
|
||||||
|
(20110101) 1 A
|
||||||
|
|
||||||
|
2011/1/2
|
||||||
|
(20110102) 1 A
|
||||||
|
>>>
|
||||||
|
1 A 20101231
|
||||||
|
$2 20110101
|
||||||
|
$2 20110102
|
||||||
|
>>>=0
|
||||||
Loading…
Reference in New Issue
Block a user