hledger icon indicating copy to clipboard operation
hledger copied to clipboard

Parsing of .timeclock files is different from Ledger's

Open the-solipsist opened this issue 7 months ago • 9 comments
trafficstars

This is a valid timeclock file for ledger (and presumably emacs):

i 2025-04-04 14:40:00 Kitchen:Timer:1   	Coffee
i 2025-04-04 14:40:00 Work:Consultancy:AcmeCorp:2   	Brief note
i 2025-04-04 14:40:00 Work:Consultancy:AcmeCorp:3   	Briefer note
i 2025-04-04 14:40:00 Work:Consultancy:AcmeCorp:4   	Briefer note
o 2025-04-04 19:09:55 Work:Consultancy:AcmeCorp:3
o 2025-04-04 19:09:55 Kitchen:Timer:1

However, this file cannot be parsed by hledger:

Expected a timeclock o entry but got i. Only one session may be clocked in at a time. Please alternate i and o, beginning with i.

hledger presumably does this because a o [date-time] entry by itself is ambiguous if there are multiple i entries: Which of the multiple i entries are you trying to close?

ledger enforces 2 rules:

  1. If there are multiple i consecutive entries, then the o entry must disambiguate by mentioning the account.
  2. There cannot be multiple i consecutive entries for the same account.

hledger ought to do the same unless there are compelling reasons not to.

the-solipsist avatar Apr 04 '25 14:04 the-solipsist

See #2362 merged yesterday :)

reesmichael1 avatar Apr 04 '25 14:04 reesmichael1

Specifically, hledger's o with no account name closes the most recent (by time) unclosed i. In my testing I thought that's what Ledger does. more details

simonmichael avatar Apr 04 '25 16:04 simonmichael

That's the fastest ever fixing of a bug that I've seen: it was fixed even before it was reported!

I ran into this ambiguity today when improving my timer helper script. Two other plaintext time trackers (https://github.com/nikolassv/bartib) and (https://github.com/jotaen/klog) don't allow multiple open tasks, while some (like https://github.com/GothenburgBitFactory/timewarrior) allow it.

But, yes, I should have checked https://github.com/simonmichael/hledger/issues/2141 and https://github.com/simonmichael/hledger/issues/2142 before opening this issue.

Specifically, hledger's o with no account name closes the most recent (by time) unclosed i. In my testing I thought that's what Ledger does. https://github.com/simonmichael/hledger/issues/2142#issuecomment-1866857286

Here's what I found:

❯ tail -n5 ~/.hours.timeclock
i 2025-04-04 14:40:00 Work:Consultancy:AcmeCorp:2   	Brief note
i 2025-04-04 14:40:00 Work:Consultancy:AcmeCorp:3   	Briefer note
i 2025-04-04 14:40:00 Work:Consultancy:AcmeCorp:4   	Briefer note
o 2025-04-04 19:09:55 Work:Consultancy:AcmeCorp:2
o 2025-04-04 19:09:55 
❯ ledger -f ~/.hours.timeclock print
While parsing file "/home/sol/.hours.timeclock", line 120:
Error: Timelog check-out event does not match any current check-ins

the-solipsist avatar Apr 04 '25 19:04 the-solipsist

If there's no ambiguity, o for ledger closes the last unclosed i. If there's ambiguity (multiple unclosed is), then account name is required. Here, for instance, the last unclosed i is closed, because AcmeCorp:3 is commented out:

❯ tail -n5 ~/.hours.timeclock
i 2025-04-04 14:40:00 Work:Consultancy:AcmeCorp:2   	Brief note
#i 2025-04-04 14:40:00 Work:Consultancy:AcmeCorp:3   	Briefer note
i 2025-04-04 14:40:00 Work:Consultancy:AcmeCorp:4   	Briefer note
o 2025-04-04 19:09:55 Work:Consultancy:AcmeCorp:2
o 2025-04-04 19:09:55 
❯ ledger -f ~/.hours.timeclock print | tail -n5
2025/04/04 () Brief note
    (Work:Consultancy:AcmeCorp:2)             16195s

2025/04/04 () Briefer note
    (Work:Consultancy:AcmeCorp:4)             16195s

Had Work:Consultancy:AcmeCorp:3 not been commented out, ledger would throw an error.

the-solipsist avatar Apr 04 '25 19:04 the-solipsist

Thanks for the testing @sol. I edited my comment to add a "more details" link as well.

hledger's o with no account name closes the most recent (by time) unclosed i

That's right, isn't it @reesmichael1 ? most recent by time, not most recent parsed ?

simonmichael avatar Apr 04 '25 21:04 simonmichael

hledger's o with no account name closes the most recent (by time) unclosed i most recent by time, not most recent parsed ?

Ambiguity only arises in 1 case:

In case there's exactly 1 unclosed i with an account name and 1 unclosed i without an account name, the situation is ambiguous.

Ledger applies the o to the closest in line order i rather than the closest in time i.

❯ tail -n3 ~/.hours.timeclock
i 2025-04-04 14:30:00 
i 2025-04-04 14:00:00 Work:Consultancy:Acme2
o 2025-04-04 15:00:00
❯ ledger -f ~/.hours.timeclock print | tail -n5
2025/04/04 () 
    (Work:Consultancy:Acme2)                   3600s

2025/04/04 () 
    ()                                        90745s

In any other case (multiple unclosed is without account names, or multiple unclosed is with account names) it'll throw an error:

❯ tail -n3~/.hours.timeclock
i 2025-04-04 14:00:00 
i 2025-04-04 15:00:00
o 2025-04-04 19:09:55 
❯ ledger -f ~/.hours.timeclock print | tail -n4
While parsing file "/home/sol/.hours.timeclock", line 116:
Error: Cannot double check-in to the same account

the-solipsist avatar Apr 05 '25 10:04 the-solipsist

hledger's usual behaviour is to prioritise dates/times rather than parse order, so I guess that will be preferable here, and hopefully we do that.

simonmichael avatar Apr 05 '25 11:04 simonmichael

Sounds good.

Given that this difference between hledger and ledger could only arise in an edge case (where parse order differs from time order) of an edge case (where there's exactly 1 open i with an account and 1 open i without an account), it might not need mentioning in the manual.

the-solipsist avatar Apr 05 '25 11:04 the-solipsist

Sorry, I was away for a few days!

That's right, isn't it @reesmichael1 ? most recent by time, not most recent parsed ?

Yes, this should be how the new feature works. I think this thread sums up the difference well--I'll admit this particular edge case isn't something I anticipated!

reesmichael1 avatar Apr 08 '25 16:04 reesmichael1

Concurrent timeclock sessions was implemented in 1.43.

simonmichael avatar Jun 14 '25 08:06 simonmichael