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 | ||||
| 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). | ||||
| 
 | ||||
|     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 | ||||
| [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