How to get next weekday number - linux

In Debian 6 Linux shell script
#!/bin/sh
backupday=$(date +%u)
assings weekday number to backupday variable.
In my Linux
Monday returns 1
Thuesday returns 2
...
Saturady returns 6
Sunday returns 7
How to get next day weekday number:
Monday should return 2
Thuesday should return 3
...
Saturady should return 7
Sunday should return 1

I think you can use the FORMAT Interpreted sequences %w instead of %u.
It start with Saturday (%w day of week (0..6); 0 is Sunday).
And it's easy to plus 1 to get what your want.
$ echo $(($(date +%w --date=Saturday) + 1))
7
$ echo $(($(date +%w --date=Sunday) + 1))
1
$ echo $(($(date +%w --date=Monday) + 1))
2

This should do:
$ echo $(( $(date +%u --date=Saturday) % 7 + 1 ))
7
$ echo $(( $(date +%u --date=Sunday) % 7 + 1 ))
1
$ echo $(( $(date +%u --date=Monday) % 7 + 1 ))
2

Related

Get date with same day in month

I want to get all dates with the same day of week.
inputDate="2021/08/25"
That means I should get all the same day of week as inputDate.
outputDates="2021/08/04,2021/08/11,2021/08/18,2021/08/25"
I only got this so far..
inputDate="2021/08/25"
dd=$(date -d "$inputDate" +"%Y/%m/%d")
So what I'm planning is to do "date -7" and loop 5 times forward and backward and collect it then check if value of month is still the same with inputDate if not then drop it
Do you have any way to do this?
Using only shell, the easyest way to get all weekdays from a month is by using cal command:
cal -n1 8 2021
outputs:
August 2021
Su Mo Tu We Th Fr Sa
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 31
Then you can filter using sed, awk or other tools to reach your goal.
Example:
year=2021
month=8
day=25
weekday_number="$(date -d$year-$month-$day +%w)"
cn=$(($weekday_number + 1))
cal -n1 $month $year |
sed -r 's/(..)\s/\1\t/g;s/ +//g' |
awk -v cn=$cn -F'\t' 'NR<3 || $cn == "" {next} {print $cn}' |
while read wday; do
echo $year/$month/$wday
done
outputs:
2021/8/4
2021/8/11
2021/8/18
2021/8/25
Without using cal or ncal...
#!/bin/bash
inputDate="2021/08/25"
dow=$(date -d "$inputDate" +"%a")
month=$(date -d "$inputDate" +"%m")
outputDates=""
for x in $(seq 0 9)
do
validDate=$(date -d "$x $dow 5 week ago" +"%Y/%m/%d" | grep "/$month/")
if [ ! -z $validDate ]
then
if [ ! -z $outputDates ]
then
outputDates="$outputDates,$validDate"
else
outputDates="$validDate"
fi
fi
done
echo "$outputDates"
This script outputs:
2021/08/04,2021/08/11,2021/08/18,2021/08/25

Schedule Cron to skip first Saturday of every month

I need a cron to skip the first Saturday of every month. I know we can run on specific days using the below command, but is there a way to skip on a particular day for every month?
//To run on first Monday of every month
0 2 * * 1 [ date '+\%m' == date '+\%m' -d "1 week ago" ] || /path/to/command
Is your command a binary file or just script?
How about the idea to add something like that in the beginning:
[ $(date | awk '{print $1}') == "Sat" ] && exit 1 || { \
# your code here
...
}
Since there seem to be no option in Cron.
I'm going with script for the above need.
**if [ $(date +%d) -le 7 ] && [ $(date +%u) -eq 1 ] ;**
[ $(date +%d) -le 7 ] - Checks if the days fall in first 7 days of month
[ $(date +%u) -eq 6 ] - Checks if day is equal to Saturday
Thanks.
The following works in cron (don't forget to escape the %):
0 2 * * * [[ `date '+\%u'` -ne '6' && `date '+\%d'` -lt '8' ]] || [[ `date '+\%d'` -gt '7' ]] && /path/to/command
The logic is :
If the day is not a Saturday and the day of the month is 1-7, execute the command
If the above is not correct, check if the day of the month is bigger than 7, if so execute
Another way would be to invert the logic :
0 2 * * * [[ ! ( `date '+\%u'` -eq '6' && `date '+\%d'` -lt '8' ) ]] && /path/to/command
The logic is :
If the day is not the first Saturday, execute the command
man 5 crontab
The "sixth" field (the rest of the line) specifies the command to be run. The entire command portion of the line, up to a newline or
a "%" character, will be executed by /bin/sh or by the shell specified in the SHELL variable of the cronfile. A "%" character in the command, unless escaped with a backslash (\), will be changed into newline characters, and all data after the first % will be sent to the command as standard input.

Set Cron Job for 1st working day of every month in Shell Scripting

I'm new to scripting language, can anyone please explain how to set the cron job for 1st working day?
You can use the following,
#monthly
Run once a month at the morning of the first day of the month.
0 0 1 * * /home/scripts/your_script_file.sh
3rd Edit:
This will run your job at morning say 10 AM on the first weekday of the month:
# First weekday of the month
# Monday - Friday
00 10 1-3 * * [ "$(date '+\%a')" == "Mon" ] && /home/scripts/your_script_file.sh
00 10 1 * * [ "$(date '+\%a')" == "Tue" ] && /home/scripts/your_script_file.sh
00 10 1 * * [ "$(date '+\%a')" == "Wed" ] && /home/scripts/your_script_file.sh
00 10 1 * * [ "$(date '+\%a')" == "Thu" ] && /home/scripts/your_script_file.sh
00 10 1 * * [ "$(date '+\%a')" == "Fri" ] && /home/scripts/your_script_file.sh
First, run the date command:
$ date '+%x'
> 12/29/2014
%x tells date to display today's date in the format of the current locale. Using that exact same format, put a list of holidays in a file called holidays. For example:
$ cat holidays
> 01/01/2015
> 07/04/2015
Next, create the following shell script:
#!/bin/sh
dom=$(date '+%d') # 01-31, day of month
year=$(date '+%Y') # four-digit year
month=$(date '+%m') # two-digit month
nworkdays=0
for d in $(seq 1 $dom)
do
today=$(date -d "$year-$month-$d" '+%x') # locale's date representation (e.g. 12/31/99)
dow=$(date -d "$year-$month-$d" '+%u') # day of week: 1-7 with 1=Monday, 7=Sunday
if [ "$dow" -le 5 ] && grep -vq "$today" /path/holidays
then
workday=Yes
nworkdays=$((nworkdays+1))
else
workday=
fi
done
[ "$workday" ] && [ "$nworkdays" -eq 1 ] && /path/command
Solution I have figured out:
0 9 1-3 * * [[ $(date +\%u) -lt 6 && (( $(date +\%d) -eq 1 || $(date +\%u) -eq 1 )) ]] && /home/scripts/your_script_file.sh
This should work:
59 6 1W * ?
Starts at AM6:59 every month at first Weekday.
a simple one run the scripte at 08:00 every first of the month for workdays Mon to Fri
00 8 1 * 1-5 /path/to/your_script_file.sh

Cron Expression for ignoring 1st Saturday of the year & run on all the Saturdays of the year

Can someone help me in building the cron expression. I've a requirement where I need to run my Job on all the Saturdays at 9:00 AM in a year excluding 1st Saturday of the year.
I had tried with the below expression, but its not working..
0 0 9 ? 1 7#2,7#3,7#4 *, 0 0 9 ? 2-12 SAT *
0 0 9 ? 1 7#2,7#3,7#4 * - It means In the month of January run my job at 9:00 AM on 2nd,3rd,4th Saturdays. But the problem here is it is taking the Last saturday only (i.e. 7#4). In some tutorials I read that comma means it considers all the values but to my surprise it is considering only the last value)
0 0 9 ? 2-12 SAT * - It means from the month of February till December I need to run my job at 9:00 AM.
I need to combine these 2 expressions in such a way it should satisfy my requirement.
Thanks In Advance
You need put compare in your program, not in cronjob. For example, in Unix shell script:
#!/usr/bin/env bash
date=$(date +%a)
month=$(date +%m)
day=$($date +%e)
if [ "$date" = "Sat" -a "$month" = "Jan" -a "$day" -lt 8 ];then
echo "Doesn't run this script at 1st Saturday of the year."
exit
fi
# put rest script
set the cronjob to run it only at 9am on Saturday
0 9 * * 6 YOUR_PROGRAM
Explanation:
%a locale's abbreviated weekday name (e.g., Sun)
%b locale's abbreviated month name (e.g., Jan)
%e day of month, space padded; same as %_d

Bash relative date (x days ago)

I have a date string that I am able to parse and format with the date command from a bash script.
But how can I determine how many days ago this date was from my script? I would like to end up with a number.
Use date itself as date value for date.
Example 5 days ago:
date -d "`date`-5days"
You can do some date arithmetics:
DATE=01/02/2010
echo $(( ( $(date +%s) - $(date -d "$DATE" +%s) ) /(24 * 60 * 60 ) ))
Convert your date and now into seconds since the epoch, subtract, divide by the number of seconds in a day:
#!/bin/bash
((a = `date -d "Wed Jan 12 02:33:22 PST 2011" +%s`))
((b = `date +%s`))
echo $(( (b-a) / (60*60*24)))

Resources