timelog: support the description field (fix #247)
This commit is contained in:
parent
fb37e99bc8
commit
5102eca9c3
@ -738,21 +738,39 @@ The original order of same-day entries will be preserved, usually.
|
||||
|
||||
### Timelog
|
||||
|
||||
hledger can also read time log files. These are (a subset of) timeclock.el's
|
||||
format, containing clock-in and clock-out entries like so:
|
||||
hledger can also read timelog files.
|
||||
[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
|
||||
o 2009/04/01 02:00:34
|
||||
i 2015/03/30 09:00:00 some:account name optional description after two spaces
|
||||
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,
|
||||
and creates a virtual transaction (or several - one per day) with the
|
||||
appropriate amount of hours. From the time log above, hledger print gives:
|
||||
The date is a [simple date](#simple-dates), so hyphen (-) and period
|
||||
(.) are also allowed as separators, leading zeroes are optional, the
|
||||
year may be omitted (and a [default year directive](#default-year) can
|
||||
be used to set it).
|
||||
|
||||
2009/03/31 * 22:21-23:59
|
||||
(projects:A) 1.64h
|
||||
|
||||
2009/04/01 * 00:00-02:00
|
||||
(projects:A) 2.01h
|
||||
The time format is HH:MM[:SS][+-ZZZZ]. Seconds and timezone are optional.
|
||||
The timezone, if present, must be four digits and is ignored
|
||||
(currently the time is always interpreted as a local time).
|
||||
|
||||
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
|
||||
[sample.timelog](https://raw.github.com/simonmichael/hledger/master/data/sample.timelog) to
|
||||
|
||||
@ -28,7 +28,7 @@ import Hledger.Data.Posting
|
||||
import Hledger.Data.Transaction
|
||||
|
||||
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
|
||||
show SetBalance = "b"
|
||||
@ -54,7 +54,7 @@ timeLogEntriesToTransactions now [i]
|
||||
| odate > idate = entryFromTimeLogInOut i o' : timeLogEntriesToTransactions now [i',o]
|
||||
| otherwise = [entryFromTimeLogInOut i o]
|
||||
where
|
||||
o = TimeLogEntry (tlsourcepos i) Out end ""
|
||||
o = TimeLogEntry (tlsourcepos i) Out end "" ""
|
||||
end = if itime > now then itime else now
|
||||
(itime,otime) = (tldatetime i,tldatetime o)
|
||||
(idate,odate) = (localDay itime,localDay otime)
|
||||
@ -84,20 +84,22 @@ entryFromTimeLogInOut i o
|
||||
tdate2 = Nothing,
|
||||
tstatus = True,
|
||||
tcode = "",
|
||||
tdescription = showtime itod ++ "-" ++ showtime otod,
|
||||
tdescription = desc,
|
||||
tcomment = "",
|
||||
ttags = [],
|
||||
tpostings = ps,
|
||||
tpreceding_comment_lines=""
|
||||
}
|
||||
showtime = take 5 . show
|
||||
acctname = tlcomment i
|
||||
itime = tldatetime i
|
||||
otime = tldatetime o
|
||||
itod = localTimeOfDay itime
|
||||
otod = localTimeOfDay otime
|
||||
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
|
||||
acctname = tlaccount i
|
||||
amount = Mixed [hrs hours]
|
||||
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 "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]
|
||||
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]
|
||||
assertEntriesGiveStrings "auto-clock-out if needed"
|
||||
[clockin (mktime today "00:00:00") ""]
|
||||
[clockin (mktime today "00:00:00") "" ""]
|
||||
["00:00-"++nowstr]
|
||||
let future = utcToLocalTime tz $ addUTCTime 100 now'
|
||||
futurestr = showtime future
|
||||
assertEntriesGiveStrings "use the clockin time for auto-clockout if it's in the future"
|
||||
[clockin future ""]
|
||||
[clockin future "" ""]
|
||||
[printf "%s-%s" futurestr futurestr]
|
||||
|
||||
]
|
||||
|
||||
@ -155,7 +155,8 @@ data TimeLogEntry = TimeLogEntry {
|
||||
tlsourcepos :: SourcePos,
|
||||
tlcode :: TimeLogCode,
|
||||
tldatetime :: LocalTime,
|
||||
tlcomment :: String
|
||||
tlaccount :: String,
|
||||
tldescription :: String
|
||||
} deriving (Eq,Ord,Typeable,Data)
|
||||
|
||||
data HistoricalPrice = HistoricalPrice {
|
||||
|
||||
@ -30,6 +30,7 @@ module Hledger.Read.JournalReader (
|
||||
datetimep,
|
||||
codep,
|
||||
accountnamep,
|
||||
modifiedaccountname,
|
||||
postingp,
|
||||
amountp,
|
||||
amountp',
|
||||
|
||||
@ -50,6 +50,7 @@ where
|
||||
import Control.Monad
|
||||
import Control.Monad.Except
|
||||
import Data.List (isPrefixOf, foldl')
|
||||
import Data.Maybe (fromMaybe)
|
||||
import Test.HUnit
|
||||
import Text.Parsec hiding (parse)
|
||||
import System.FilePath
|
||||
@ -58,7 +59,7 @@ import Hledger.Data
|
||||
-- XXX too much reuse ?
|
||||
import Hledger.Read.JournalReader (
|
||||
directive, historicalpricedirective, defaultyeardirective, emptyorcommentlinep, datetimep,
|
||||
parseJournalWith, getParentAccount
|
||||
parseJournalWith, modifiedaccountname
|
||||
)
|
||||
import Hledger.Utils
|
||||
|
||||
@ -104,8 +105,9 @@ timelogentry = do
|
||||
code <- oneOf "bhioO"
|
||||
many1 spacenonewline
|
||||
datetime <- datetimep
|
||||
comment <- optionMaybe (many1 spacenonewline >> liftM2 (++) getParentAccount restofline)
|
||||
return $ TimeLogEntry sourcepos (read [code]) datetime (maybe "" rstrip comment)
|
||||
account <- fromMaybe "" <$> optionMaybe (many1 spacenonewline >> modifiedaccountname)
|
||||
description <- fromMaybe "" <$> optionMaybe (many1 spacenonewline >> restofline)
|
||||
return $ TimeLogEntry sourcepos (read [code]) datetime account description
|
||||
|
||||
tests_Hledger_Read_TimelogReader = TestList [
|
||||
]
|
||||
|
||||
@ -1,12 +1,22 @@
|
||||
# a timelog session is parsed as a similarly-named transaction with one virtual posting
|
||||
hledgerdev -f - print
|
||||
<<<
|
||||
i 2009/1/1 08:00:00 something
|
||||
o 2009/1/1 09:00:00
|
||||
i 2009/1/1 08: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
|
||||
(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
|
||||
>>>= 0
|
||||
|
||||
Loading…
Reference in New Issue
Block a user