timewarrior icon indicating copy to clipboard operation
timewarrior copied to clipboard

`:lastweek` doesn't count last Sunday

Open sskras opened this issue 2 years ago • 6 comments

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.

sskras avatar Jun 13 '22 15:06 sskras

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

sskras avatar Jun 13 '22 15:06 sskras

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.

sskras avatar Jun 13 '22 15:06 sskras

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=

sskras avatar Jul 06 '22 15:07 sskras

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?

sskras avatar Jul 06 '22 17:07 sskras

The start of week is "calculated" by libshared which sets it to Monday. See src/libshared/src/Datetime.cpp:63

lauft avatar Aug 17 '22 05:08 lauft

@lauft do you mean this?

int Datetime::weekstart = 1; // Monday, per ISO-8601.

taskwarrior has rc.weekstart but timewarrior does not perhaps

smemsh avatar Aug 19 '22 00:08 smemsh

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
                                                   

perdalum avatar May 31 '23 14:05 perdalum

Thanks, @perdalum! I noticed this exact issue and your patch did the trick.

egyptianbman avatar Aug 06 '23 04:08 egyptianbman

@lauft

The start of week is "calculated" by libshared which sets it to Monday. See src/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.

serg-z avatar Aug 14 '23 15:08 serg-z

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 avatar Aug 14 '23 15:08 egyptianbman

@egyptianbman

There is no eow time, the DateTime 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 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".

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.

serg-z avatar Aug 14 '23 16:08 serg-z

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.

serg-z avatar Aug 14 '23 17:08 serg-z

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

Rahlir avatar Oct 01 '23 18:10 Rahlir

ping @lauft :)

sskras avatar Oct 01 '23 19:10 sskras

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

lauft avatar Oct 04 '23 20:10 lauft