hledger
hledger copied to clipboard
Internal representations of time entries are rounded
Thanks very much for the great software, I've really been enjoying using it.
I've been working with timeclock files, and I believe I may have found an issue with how time entries are rounded, though I'm not sure what the correct/intended behaviour should be.
Based on this comment, it sounds like the intent is for time entries to be represented internally as seconds, but be displayed as hours rounded to 2 decimal places?
However, it looks like the current implementation (tested in versions 1.30 and 1.22 on Ubuntu) represents each time entry internally as hours to 2 decimal places, which can lead to some unintuitive results. In the example below, despite logging a total of 2 minutes against each account, the two 1-minute entries for account a
result in a greater total than the single 2-minute entry for account b
:
$ cat test.timeclock
i 2023-07-17 09:00:00 a
o 2023-07-17 09:01:00
i 2023-07-17 10:00:00 a
o 2023-07-17 10:01:00
i 2023-07-17 11:00:00 b
o 2023-07-17 11:02:00
$ hledger -f test.timeclock bal
0.04h a
0.03h b
--------------------
0.07h
Version 1.21 has an issue with printing many decimal places, but version 1.20.4 appears to use internal representations with resolution in seconds, giving different (and arguably more accurate) results:
$ hledger-1.20.4 -f test.timeclock bal
0.03h a
0.03h b
--------------------
0.07h
However, because version 1.20.4 still prints transactions in hours to 2 decimal places, there is a loss of resolution when printing transactions:
$ hledger-1.20.4 -f test.timeclock print
2023-07-17 * 09:00-09:01
(a) 0.02h
2023-07-17 * 10:00-10:01
(a) 0.02h
2023-07-17 * 11:00-11:02
(b) 0.03h
$ hledger-1.20.4 -f test.timeclock print | hledger-1.20.4 -f - bal
0.04h a
0.03h b
--------------------
0.07h
I'm not sure how simple/feasible it would be, but it seems like the desired behaviour would be to handle time entries like ledger does: representing them internally as seconds, printing transactions in seconds, and formatting in minutes/hours where appropriate:
$ ledger -f test.timeclock print
2023/07/17 ()
(a) 60s
2023/07/17 ()
(a) 60s
2023/07/17 ()
(b) 120s
$ ledger -f test.timeclock print | ledger -f - bal
2.0m a
2.0m b
--------------------
4.0m
It seems like this might require a reader that parses timeclock files as a seconds (s
) commodity, and then with minute/hour formatting handled with something like ledger's C
directive:
C 1 m = 60 s
C 1 h = 60 m
Good example! It gives a strange balance report since 1.22, as you say. I welcome any help with this.
Thanks @simonmichael, happy to help out if I can, though Haskell is a bit new to me :slightly_smiling_face:
Any thoughts on the direction for the fix? Does recording time in seconds instead of hours sound feasible? It looks like it would be a reasonably straightforward change to TimedotReader.hs and Timeclock.hs to create postings in seconds instead of hours, but I don't know what would need to be changed to support the C
Directive to treat hours/minutes/seconds as a single commodity that can be recorded and displayed in different ways.
Switching to seconds as the internal commodity does sound sensible, but I'm not exactly sure how to make it fit. Ideally the external behaviour would remain the same at least by default, except with more consistent balance reports as in 1.21. But maybe that's not practical ?
Ie, will this force us to finally add some kind of C
support, or some other way of displaying different units from what was parsed ? But how did 1.21 manage it ?
How did 1.20 manage it I should say (ignoring 1.21 which had a decimal rendering bug).