timewarrior
timewarrior copied to clipboard
`:lastweek` doesn't count last Sunday
Cleaning the state:
$ timew --version
1.4.3-dev
$ TIMEWARRIORDB=/tmp/timewarriordb
$ export TIMEWARRIORDB
$ rm -rfv ${TIMEWARRIORDB}
$ mkdir -v ${TIMEWARRIORDB}
mkdir: created directory '/tmp/timewarriordb'
$ > ${TIMEWARRIORDB}/timewarrior.cfg
$ timew summ :lastweek
No filtered data found in the range 2022-06-06T00:00:00 - 2022-06-12T00:00:00.
Mark up last week (it start from monday here):
$ cal -m
June 2022
Mo Tu We Th Fr Sa Su
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
$ timew track 2022-06-11T06:00 - 2022-06-11T07:00
Recorded
Started 2022-06-11T06:00:00
Ended 07:00:00
Total 1:00:00
$ timew track 2022-06-12T06:00 - 2022-06-12T07:00
Recorded
Started 2022-06-12T06:00:00
Ended 07:00:00
Total 1:00:00
Let's check the time spent:
$ timew summ :lastweek
Wk Date Day Tags Start End Time Total
W23 2022-06-11 Sat 6:00:00 7:00:00 1:00:00 1:00:00
1:00:00
$ timew summ :month
Wk Date Day Tags Start End Time Total
W23 2022-06-11 Sat 6:00:00 7:00:00 1:00:00 1:00:00
W23 2022-06-12 Sun 6:00:00 7:00:00 1:00:00 1:00:00
2:00:00
For some reason :lastweek
misses the second track (from Sunday), even if :month
shows the same week number for both tracks.
Configuration (just in case):
$ timew config
color = on
confirmation = on
debug = off
journal:
size = -1
define reports:
day:
axis = internal
cell = 15
day = yes
holidays = no
hours = all
lines = 2
month = no
spacing = 1
summary = yes
totals = no
week = no
weekday = yes
gaps:
range = :day
month:
cell = 15
day = yes
holidays = yes
hours = all
lines = 1
month = yes
spacing = 1
summary = yes
totals = yes
week = yes
weekday = yes
summary:
holidays = yes
week:
cell = 15
day = yes
holidays = yes
hours = all
lines = 1
month = no
spacing = 1
summary = yes
totals = yes
week = yes
weekday = yes
define theme:
colors:
exclusion = gray8 on gray4
holiday = gray4
label = gray4
today = white
description = Built-in default
verbose = on
OK, seems like it comes from the system configuration:
$ locale -k LC_TIME | grep day
abday="Sun;Mon;Tue;Wed;Thu;Fri;Sat"
day="Sunday;Monday;Tuesday;Wednesday;Thursday;Friday;Saturday"
So I will need to reconfigure my system (MSYS2), it seems. Sorry for the noise.
I guess that check was flawed. The right one should search for first_weekday
, I guess:
$ locale -k LC_TIME | grep weekday
This returns nothing on MSYS2. But it returns an integer value on my Ubuntu:
$ ssh vps1130070 lsb_release -d
Description: Ubuntu 20.04.4 LTS
$ ssh vps1130070 locale -k LC_TIME | grep weekday
first_weekday=2
$ ssh vps1130070 locale
LANG=en_GB.UTF-8
LANGUAGE=
LC_CTYPE="en_GB.UTF-8"
LC_NUMERIC="en_GB.UTF-8"
LC_TIME="en_GB.UTF-8"
LC_COLLATE="en_GB.UTF-8"
LC_MONETARY="en_GB.UTF-8"
LC_MESSAGES="en_GB.UTF-8"
LC_PAPER="en_GB.UTF-8"
LC_NAME="en_GB.UTF-8"
LC_ADDRESS="en_GB.UTF-8"
LC_TELEPHONE="en_GB.UTF-8"
LC_MEASUREMENT="en_GB.UTF-8"
LC_IDENTIFICATION="en_GB.UTF-8"
LC_ALL=
Well, my hypothesis regarding LC_TIME settings seems to be wrong, at least on Ubuntu 20.04:
I have configured my locale, where I set both first_weekday
and first_workday
to 2
:
$ locale -k LC_TIME | grep -e ^day -e ^first
day="Sunday;Monday;Tuesday;Wednesday;Thursday;Friday;Saturday"
first_weekday=2
first_workday=2
This week now starts on Monday, 2022-07-04:
$ ncal -3
June 2022 July 2022 August 2022
Mo 6 13 20 27 4 11 18 25 1 8 15 22 29
Tu 7 14 21 28 5 12 19 26 2 9 16 23 30
We 1 8 15 22 29 6 13 20 27 3 10 17 24 31
Th 2 9 16 23 30 7 14 21 28 4 11 18 25
Fr 3 10 17 24 1 8 15 22 29 5 12 19 26
Sa 4 11 18 25 2 9 16 23 30 6 13 20 27
Su 5 12 19 26 3 10 17 24 31 7 14 21 28
Let's reinitialize the TimeWarrior DB:
$ TIMEWARRIORDB=/tmp/timewarriordb
$ export TIMEWARRIORDB
$ rm -rf ${TIMEWARRIORDB}
$ mkdir -v ${TIMEWARRIORDB}
mkdir: created directory '/tmp/timewarriordb'
$ > ${TIMEWARRIORDB}/timewarrior.cfg
TimeWarrior searches for tracks in seemingly the correct time range:
$ timew summ :lastweek
No filtered data found in the range 2022-06-27T00:00:00 - 2022-07-04T00:00:00.
Now if I reconfigure locale by setting both first_weekday
and first_workday
to 1
:
$ locale -k LC_TIME | grep -e ^day -e ^first
day="Sunday;Monday;Tuesday;Wednesday;Thursday;Friday;Saturday"
first_weekday=1
first_workday=1
... this week starts on Sunday, 2022-07-03:
$ ncal -3
June 2022 July 2022 August 2022
Su 5 12 19 26 3 10 17 24 31 7 14 21 28
Mo 6 13 20 27 4 11 18 25 1 8 15 22 29
Tu 7 14 21 28 5 12 19 26 2 9 16 23 30
We 1 8 15 22 29 6 13 20 27 3 10 17 24 31
Th 2 9 16 23 30 7 14 21 28 4 11 18 25
Fr 3 10 17 24 1 8 15 22 29 5 12 19 26
Sa 4 11 18 25 2 9 16 23 30 6 13 20 27
I reinitialize TimeWarrior DB again:
$ rm -rf ${TIMEWARRIORDB}
$ mkdir -v ${TIMEWARRIORDB}
mkdir: created directory '/tmp/timewarriordb'
$ > ${TIMEWARRIORDB}/timewarrior.cfg
... but TimeWarrior still searches for tracks up to the 2022-07-04T00:00 (start of Monday) for some reason:
$ timew summ :lastweek
No filtered data found in the range 2022-06-27T00:00:00 - 2022-07-04T00:00:00.
Which now is off by one day.
It seems that ncal
respects my LC_TIME
settings, but timew
does not.
So on Ubuntu it starts counting a week on Mondays. And on my Windows machines (MSYS2 environment) it starts counting week days on Sunday.
Does anyone know how TimeWarrior calculates start and stop of the week?
The start of week is "calculated" by libshared
which sets it to Monday. See src/libshared/src/Datetime.cpp:63
@lauft do you mean this?
int Datetime::weekstart = 1; // Monday, per ISO-8601.
taskwarrior has rc.weekstart
but timewarrior does not perhaps
I stumpled upon the same problem and I think I've found another root cause. If I change a single line in helper.cpp and subtract 6 from end day instead of 7, it works. My guess is that the :lastweek range ends at Saturday 23:59:59 (Sunday is NOT included in the range) instead of Sunday at midnight (Monday at 0:00:00).
Below is what I did:
$ timewarrior >: date
Ons 31 Maj 2023 16:12:16 CEST
$ timewarrior >: ncal
Maj 2023
Ma 1 8 15 22 29
Ti 2 9 16 23 30
On 3 10 17 24 31
To 4 11 18 25
Fr 5 12 19 26
Lø 6 13 20 27
Sø 7 14 21 28
$ timewarrior >: src/timew summary week :lastweek
Wk Date Day Tags Start End Time Total
W21 2023-05-26 Fri work 7:44:00 15:10:00 7:26:00 7:26:00
W21 2023-05-27 Sat work 10:51:12 11:02:35 0:11:23
work 11:15:27 12:23:44 1:08:17
work 16:22:18 16:37:48 0:15:30
work 19:55:00 20:22:52 0:27:52 2:03:02
9:29:02
# :lastweek should go from 2023-05-22T00:00:00 - 2023-05-28T23:59:59
# but I think it goes from 2023-05-22T00:00:00 - 2023-05-28T00:00:00
$ timewarrior >: bbedit src/helper.cpp
$ timewarrior >: git diff src/helper.cpp
diff --git a/src/helper.cpp b/src/helper.cpp
index dfcf447e..872ea95c 100644
--- a/src/helper.cpp
+++ b/src/helper.cpp
@@ -216,7 +216,7 @@ bool expandIntervalHint (
sd += Datetime::daysInMonth (sy, sm);
}
- ed -= 7;
+ ed -= 6;
if (ed < 1)
{
--em;
$ timewarrior >: make
[ 0%] Building CXX object src/CMakeFiles/timew.dir/helper.cpp.o
[ 0%] Linking CXX static library libtimew.a
[ 25%] Built target timew
[ 41%] Built target libshared
[ 41%] Built target generate_additional_help
[ 67%] Built target commands
[ 68%] Linking CXX executable timew
[ 69%] Built target timew_executable
[ 69%] Linking CXX executable lex
[ 70%] Built target lex_executable
[ 75%] Built target man7
[100%] Built target man1
[100%] Built target doc
$ timewarrior >: src/timew summary week :lastweek
Wk Date Day Tags Start End Time Total
W21 2023-05-26 Fri work 7:44:00 15:10:00 7:26:00 7:26:00
W21 2023-05-27 Sat work 10:51:12 11:02:35 0:11:23
work 11:15:27 12:23:44 1:08:17
work 16:22:18 16:37:48 0:15:30
work 19:55:00 20:22:52 0:27:52 2:03:02
W21 2023-05-28 Sun 5:00:00 17:55:00 12:55:00 12:55:00
22:24:02
Thanks, @perdalum! I noticed this exact issue and your patch did the trick.
@lauft
The start of week is "calculated" by
libshared
which sets it to Monday. Seesrc/libshared/src/Datetime.cpp:63
It seems to me that the issue is that the eow
Datetime
is initialized correctly in the beginning:
Datetime eow ("eow");
Then shifting calculations happen and afterwards the range end is assigned a Datetime
initialized with calculated values:
range.end = Datetime (ey, em, ed);
But the eow
time is discarded, so it's set to the midnight of the end day, thus excluding the [00:00:01 - 23:59:59] segment of that day, as I understand.
There is no eow
time, the DateTime
object is only holding dates. The discrepancy is adjusted for in other parts of the code, i.e. here.
The issue is that while start of week is Monday
, end of week is Sunday
and when not accounting for time, end of week needs to be the following Monday
. In lieu of changing this to subtract 6, you can instead change this to sonw
-- or "start of next week".
You can run timew with debug to see a hint of the dates being evaluated:
timew :debug :lastmonth summary
@egyptianbman
There is no
eow
time, theDateTime
object is only holding dates.
The Datetime
class, hence the name, holds the date and time (i.e. 'timestamp') in the _date
variable of time_t
type. It even has a constructor for specifying the time:
Datetime::Datetime (const int y, const int m, const int d, const int hr, const int mi, const int se)
eow
is a special kind of Datetime
, initialized here. There's an example of the eow
value in the beginning of the file:
// Example Notes
// ------------------- ------------------
// eow 2017-03-05T23:59:59 Unaffected
The discrepancy is adjusted for in other parts of the code, i.e. here.
That's a different and unrelated to :lastweek
branch of the conditional statement, which gets executed when the hint is a day name.
The issue is that while start of week is
Monday
, end of week isSunday
and when not accounting for time, end of week needs to be the followingMonday
. In lieu of changing this to subtract 6, you can instead change this tosonw
-- or "start of next week".
In the case of :lastweek
that would include the midnight of the current week's Monday, which is incorrect, in my opinion. I think that a correct solution would be accounting for time and setting it to the last second of the last week's Sunday.
IMHO, using "start of next X" in most hints is incorrect in general, but I don't rule out that there's a reason, that I'm not aware of, for doing it this way.
I've checked the rest of the hints and they all include midnight of the next day after their actual span. So I guess that's intended behavior, even though not what I initially and intuitively expected.
There's an issue with :lastweek
, obviously, but also there's an issue with "day name" hints. They're all described as "Previous <day name>", but for the current weekday they wouldn't use the previous, they'd use the current day's range.
So, is there a fix for this being implemented? It looks like the most obvious fix is the one proposed by @egyptianbman and @perdalum , maybe one of you could submit PR for this? Thanks for looking into this
ping @lauft :)
I favor the fix changing the code from using eow
to sonw
in line 198 in helper.cpp
.
This is in line with the changes made in lines 148-154 when the eo*
named dates were changed to point to the last second of the respective interval (see also GothenburgBitFactory/taskwarrior#2519).