Single-line solution for any day week without loops
MON=1
TUE=2
WED=3
THU=4
FRI=5
SAT=6
SUN=7
echo "Today " && date
echo "Next Monday " && date -d "+ $(( ( (6 + $MON - $(date +%u)) % 7) + 1 )) days"
echo "Next Tuesday " && date -d "+ $(( ( (6 + $TUE - $(date +%u)) % 7) + 1 )) days"
echo "Next Wednesday " && date -d "+ $(( ( (6 + $WED - $(date +%u)) % 7) + 1 )) days"
echo "Next Thursday " && date -d "+ $(( ( (6 + $THU - $(date +%u)) % 7) + 1 )) days"
echo "Next Friday " && date -d "+ $(( ( (6 + $FRI - $(date +%u)) % 7) + 1 )) days"
echo "Next Saturday " && date -d "+ $(( ( (6 + $SAT - $(date +%u)) % 7) + 1 )) days"
echo "Next Sunday " && date -d "+ $(( ( (6 + $SUN - $(date +%u)) % 7) + 1 )) days"
Output
Today
Thu, Nov 12, 2020 10:24:38 PM
Next Monday
Mon, Nov 16, 2020 10:24:39 PM
Next Tuesday
Tue, Nov 17, 2020 10:24:40 PM
Next Wednesday
Wed, Nov 18, 2020 10:24:40 PM
Next Thursday
Thu, Nov 19, 2020 10:24:41 PM
Next Friday
Fri, Nov 13, 2020 10:24:42 PM
Next Saturday
Sat, Nov 14, 2020 10:24:42 PM
Next Sunday
Sun, Nov 15, 2020 10:24:43 PM
Explanation
Idea is to calculate number of days until next day of week and add these number to current date. Let's take Saturday as example.
- On Monday add 5 days
- ...
- On Friday add 1 day
- On Saturday add 7 days
- On Sunday add 6 days
So first iteration of algorithm looks like take current day of week date +%u
, take mod 7
and add 1
because modulo is zero based:
( $(date +%u) % 7) + 1
However, it does not take into account that our sequence of days to add is descending (5,4,3,2,1,7,6). To accommodate this we have to subtract current day of week from 7
, then take modulo and add 1
:
( (7 - $(date +%u)) % 7) + 1
So we got working example for Monday (7 == 6 + $MON
). To make it searching any week of day we should re-write it like
( (6 + <DAY> - $(date +%u)) % 7) + 1
where <DAY>
should be any of variables above ($MON
...$SUN
)
Modification for Alpine Linux
Alpine Linux does not support -d "+ 3 days"
so you either install coreutils
(apk add coreutils
) to make it working or do days arithmetic by yourself.
date -d "@$(($(date +%s) + 86400 * $(( ( (6 + $SAT - $(date +%u)) % 7) + 1 )) ))"
Explanation
$(date +%s)
outputs number of seconds since ... you know! 86400
is number of seconds per day, date -d "@<number_of_seconds>"
restores date from modified number of seconds.
Modification for Mac OS
It works like "Modification for Alpine Linux" except on MacOS, instead of date -d "@<number_of_seconds>"
you write date -r "<number_of_seconds>"
, so
date -r "$(($(date +%s) + 86400 * $(( ( (6 + $SAT - $(date +%u)) % 7) + 1 )) ))"
See "Modification for Alpine Linux/Explanation" above for more details.