timelog: support the description field (fix #247)

This commit is contained in:
Simon Michael 2015-04-28 13:54:36 -07:00
parent fb37e99bc8
commit 5102eca9c3
6 changed files with 62 additions and 28 deletions

View File

@ -738,21 +738,39 @@ The original order of same-day entries will be preserved, usually.
### Timelog ### Timelog
hledger can also read time log files. These are (a subset of) timeclock.el's hledger can also read timelog files.
format, containing clock-in and clock-out entries like so: [As with Ledger](http://ledger-cli.org/3.0/doc/ledger3.html#Time-Keeping),
these are (a subset of)
[timeclock.el](http://www.emacswiki.org/emacs/TimeClock)'s format,
containing clock-in and clock-out entries like so:
i 2009/03/31 22:21:45 projects:A i 2015/03/30 09:00:00 some:account name optional description after two spaces
o 2009/04/01 02:00:34 o 2015/03/30 09:20:00
i 2015/03/31 22:21:45 another account
o 2015/04/01 02:00:34
hledger treats the clock-in description ("projects:A") as an account name, The date is a [simple date](#simple-dates), so hyphen (-) and period
and creates a virtual transaction (or several - one per day) with the (.) are also allowed as separators, leading zeroes are optional, the
appropriate amount of hours. From the time log above, hledger print gives: year may be omitted (and a [default year directive](#default-year) can
be used to set it).
2009/03/31 * 22:21-23:59 The time format is HH:MM[:SS][+-ZZZZ]. Seconds and timezone are optional.
(projects:A) 1.64h The timezone, if present, must be four digits and is ignored
(currently the time is always interpreted as a local time).
2009/04/01 * 00:00-02:00
(projects:A) 2.01h hledger treats each clock-in/clock-out pair as a transaction posting
some number of hours to a (single) account. Or, several transactions
if the session spans more than one day. Eg for the above time log,
hledger print gives:
2015/03/30 * optional description after two spaces
(some:account name) 0.33h
2015/03/31 * 22:21-23:59
(another account) 1.64h
2015/04/01 * 00:00-02:00
(another account) 2.01h
Here is a Here is a
[sample.timelog](https://raw.github.com/simonmichael/hledger/master/data/sample.timelog) to [sample.timelog](https://raw.github.com/simonmichael/hledger/master/data/sample.timelog) to

View File

@ -28,7 +28,7 @@ import Hledger.Data.Posting
import Hledger.Data.Transaction import Hledger.Data.Transaction
instance Show TimeLogEntry where instance Show TimeLogEntry where
show t = printf "%s %s %s" (show $ tlcode t) (show $ tldatetime t) (tlcomment t) show t = printf "%s %s %s %s" (show $ tlcode t) (show $ tldatetime t) (tlaccount t) (tldescription t)
instance Show TimeLogCode where instance Show TimeLogCode where
show SetBalance = "b" show SetBalance = "b"
@ -54,7 +54,7 @@ timeLogEntriesToTransactions now [i]
| odate > idate = entryFromTimeLogInOut i o' : timeLogEntriesToTransactions now [i',o] | odate > idate = entryFromTimeLogInOut i o' : timeLogEntriesToTransactions now [i',o]
| otherwise = [entryFromTimeLogInOut i o] | otherwise = [entryFromTimeLogInOut i o]
where where
o = TimeLogEntry (tlsourcepos i) Out end "" o = TimeLogEntry (tlsourcepos i) Out end "" ""
end = if itime > now then itime else now end = if itime > now then itime else now
(itime,otime) = (tldatetime i,tldatetime o) (itime,otime) = (tldatetime i,tldatetime o)
(idate,odate) = (localDay itime,localDay otime) (idate,odate) = (localDay itime,localDay otime)
@ -84,20 +84,22 @@ entryFromTimeLogInOut i o
tdate2 = Nothing, tdate2 = Nothing,
tstatus = True, tstatus = True,
tcode = "", tcode = "",
tdescription = showtime itod ++ "-" ++ showtime otod, tdescription = desc,
tcomment = "", tcomment = "",
ttags = [], ttags = [],
tpostings = ps, tpostings = ps,
tpreceding_comment_lines="" tpreceding_comment_lines=""
} }
showtime = take 5 . show
acctname = tlcomment i
itime = tldatetime i itime = tldatetime i
otime = tldatetime o otime = tldatetime o
itod = localTimeOfDay itime itod = localTimeOfDay itime
otod = localTimeOfDay otime otod = localTimeOfDay otime
idate = localDay itime idate = localDay itime
desc | null (tldescription i) = showtime itod ++ "-" ++ showtime otod
| otherwise = tldescription i
showtime = take 5 . show
hours = elapsedSeconds (toutc otime) (toutc itime) / 3600 where toutc = localTimeToUTC utc hours = elapsedSeconds (toutc otime) (toutc itime) / 3600 where toutc = localTimeToUTC utc
acctname = tlaccount i
amount = Mixed [hrs hours] amount = Mixed [hrs hours]
ps = [posting{paccount=acctname, pamount=amount, ptype=VirtualPosting, ptransaction=Just t}] ps = [posting{paccount=acctname, pamount=amount, ptype=VirtualPosting, ptransaction=Just t}]
@ -122,18 +124,18 @@ tests_Hledger_Data_TimeLog = TestList [
assertEntriesGiveStrings name es ss = assertEqual name ss (map tdescription $ timeLogEntriesToTransactions now es) assertEntriesGiveStrings name es ss = assertEqual name ss (map tdescription $ timeLogEntriesToTransactions now es)
assertEntriesGiveStrings "started yesterday, split session at midnight" assertEntriesGiveStrings "started yesterday, split session at midnight"
[clockin (mktime yesterday "23:00:00") ""] [clockin (mktime yesterday "23:00:00") "" ""]
["23:00-23:59","00:00-"++nowstr] ["23:00-23:59","00:00-"++nowstr]
assertEntriesGiveStrings "split multi-day sessions at each midnight" assertEntriesGiveStrings "split multi-day sessions at each midnight"
[clockin (mktime (addDays (-2) today) "23:00:00") ""] [clockin (mktime (addDays (-2) today) "23:00:00") "" ""]
["23:00-23:59","00:00-23:59","00:00-"++nowstr] ["23:00-23:59","00:00-23:59","00:00-"++nowstr]
assertEntriesGiveStrings "auto-clock-out if needed" assertEntriesGiveStrings "auto-clock-out if needed"
[clockin (mktime today "00:00:00") ""] [clockin (mktime today "00:00:00") "" ""]
["00:00-"++nowstr] ["00:00-"++nowstr]
let future = utcToLocalTime tz $ addUTCTime 100 now' let future = utcToLocalTime tz $ addUTCTime 100 now'
futurestr = showtime future futurestr = showtime future
assertEntriesGiveStrings "use the clockin time for auto-clockout if it's in the future" assertEntriesGiveStrings "use the clockin time for auto-clockout if it's in the future"
[clockin future ""] [clockin future "" ""]
[printf "%s-%s" futurestr futurestr] [printf "%s-%s" futurestr futurestr]
] ]

View File

@ -155,7 +155,8 @@ data TimeLogEntry = TimeLogEntry {
tlsourcepos :: SourcePos, tlsourcepos :: SourcePos,
tlcode :: TimeLogCode, tlcode :: TimeLogCode,
tldatetime :: LocalTime, tldatetime :: LocalTime,
tlcomment :: String tlaccount :: String,
tldescription :: String
} deriving (Eq,Ord,Typeable,Data) } deriving (Eq,Ord,Typeable,Data)
data HistoricalPrice = HistoricalPrice { data HistoricalPrice = HistoricalPrice {

View File

@ -30,6 +30,7 @@ module Hledger.Read.JournalReader (
datetimep, datetimep,
codep, codep,
accountnamep, accountnamep,
modifiedaccountname,
postingp, postingp,
amountp, amountp,
amountp', amountp',

View File

@ -50,6 +50,7 @@ where
import Control.Monad import Control.Monad
import Control.Monad.Except import Control.Monad.Except
import Data.List (isPrefixOf, foldl') import Data.List (isPrefixOf, foldl')
import Data.Maybe (fromMaybe)
import Test.HUnit import Test.HUnit
import Text.Parsec hiding (parse) import Text.Parsec hiding (parse)
import System.FilePath import System.FilePath
@ -58,7 +59,7 @@ import Hledger.Data
-- XXX too much reuse ? -- XXX too much reuse ?
import Hledger.Read.JournalReader ( import Hledger.Read.JournalReader (
directive, historicalpricedirective, defaultyeardirective, emptyorcommentlinep, datetimep, directive, historicalpricedirective, defaultyeardirective, emptyorcommentlinep, datetimep,
parseJournalWith, getParentAccount parseJournalWith, modifiedaccountname
) )
import Hledger.Utils import Hledger.Utils
@ -104,8 +105,9 @@ timelogentry = do
code <- oneOf "bhioO" code <- oneOf "bhioO"
many1 spacenonewline many1 spacenonewline
datetime <- datetimep datetime <- datetimep
comment <- optionMaybe (many1 spacenonewline >> liftM2 (++) getParentAccount restofline) account <- fromMaybe "" <$> optionMaybe (many1 spacenonewline >> modifiedaccountname)
return $ TimeLogEntry sourcepos (read [code]) datetime (maybe "" rstrip comment) description <- fromMaybe "" <$> optionMaybe (many1 spacenonewline >> restofline)
return $ TimeLogEntry sourcepos (read [code]) datetime account description
tests_Hledger_Read_TimelogReader = TestList [ tests_Hledger_Read_TimelogReader = TestList [
] ]

View File

@ -1,12 +1,22 @@
# a timelog session is parsed as a similarly-named transaction with one virtual posting # a timelog session is parsed as a similarly-named transaction with one virtual posting
hledgerdev -f - print hledgerdev -f - print
<<< <<<
i 2009/1/1 08:00:00 something i 2009/1/1 08:00:00
o 2009/1/1 09:00:00 o 2009/1/1 09:00:00 stuff on checkout record is ignored
i 2009/1/2 08:00:00 account name
o 2009/1/2 09:00:00
i 2009/1/3 08:00:00 some:account name and a description
o 2009/1/3 09:00:00
>>> >>>
2009/01/01 * 08:00-09:00 2009/01/01 * 08:00-09:00
(something) 1.00h () 1.00h
2009/01/02 * 08:00-09:00
(account name) 1.00h
2009/01/03 * and a description
(some:account name) 1.00h
>>>2 >>>2
>>>= 0 >>>= 0