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 | ### 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 | ||||||
|  | |||||||
| @ -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] | ||||||
| 
 | 
 | ||||||
|  ] |  ] | ||||||
|  | |||||||
| @ -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 { | ||||||
|  | |||||||
| @ -30,6 +30,7 @@ module Hledger.Read.JournalReader ( | |||||||
|   datetimep, |   datetimep, | ||||||
|   codep, |   codep, | ||||||
|   accountnamep, |   accountnamep, | ||||||
|  |   modifiedaccountname, | ||||||
|   postingp, |   postingp, | ||||||
|   amountp, |   amountp, | ||||||
|   amountp', |   amountp', | ||||||
|  | |||||||
| @ -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 [ | ||||||
|  ] |  ] | ||||||
|  | |||||||
| @ -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 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user