I am writing a bash script that needs to print the date of the last working day. So for example if the script is run on a Monday, it will print the date for last Friday.
I found that this prints yesterdays date:
date -d '1 day ago' +'%Y/%m/%d'
I also know that I can get the day of the week by using this statement
date +%w
I want to combine these two statements in order to have a little helper script that prints the required date. The logic goes something like this (note: its Pseudo code - I've never written a bash script)
DAY_OF_WEEK = `date +%w`
if (%DAY_OF_WEEK == 1)
LOOK_BACK = 3
elif
LOOK_BACK = 1
fi
echo `date -d '%LOOK_BACK day ago' +'%Y/%m/%d'`
Can someone help by correcting the pseudo code above?
(I am running on Ubuntu 10.0.4)
You were so close:
day_or_week=`date +%w`
if [ $day_or_week == 1 ] ; then
look_back=3
else
look_back=1
fi
date -d "$look_back day ago" +'%Y/%m/%d'
Sunday also needs to be checked.
DAY_OF_WEEK=`date +%w`
if [ $DAY_OF_WEEK = 0 ] ; then
LOOK_BACK=2
elif [ $DAY_OF_WEEK = 1 ] ; then
LOOK_BACK=3
else
LOOK_BACK=1
fi
date -d "$LOOK_BACK day ago" +'%Y/%m/%d'
I'm using a Mac, so my date command doesn't have the same -d flag yours seems to, but the following should work if it behaves as you've indicated:
if [[ $(date +%w) == 1 ]]
then
LOOK_BACK=3
else
LOOK_BACK=1
fi
date -d "${LOOK_BACK} day ago" +%Y/%m/%d
For OSX (tested on 10.9.2 and 10.13.4), so probably any environment where you are using BSD date.
if [ $(date +%w) == 1 ] ; then
date -v-3d +'%Y/%m/%d'
else
date -v-1d +'%Y/%m/%d'
fi
You can check to see if you are using BSD date by
$ man date | grep "BSD General"
Putting the other answers together, I came up with this:
last_workday() {
from_date="${#:-today}"
day_of_week=$(date +%w --date="${from_date}")
if [ ${day_of_week} = "0" ] ; then
look_back=2
elif [ ${day_of_week} = "1" ] ; then
look_back=3
else
look_back=1
fi
date -d "${from_date} - ${look_back} day" +'%Y/%m/%d'
}
next_workday() {
from_date="${#:-today}"
day_of_week=$(date +%w --date="${from_date}")
if [ ${day_of_week} = "5" ] ; then
look_forward=3
elif [ ${day_of_week} = "6" ] ; then
look_forward=2
else
look_back=1
fi
date -d "${from_date} + ${look_forward} day" +'%Y/%m/%d'
}
for i in $(seq 16); do
now=$(date +'%Y/%m/%d' --date="today + ${i} day")
prev=$(last_workday "${now}")
next=$(next_workday "${now}")
echo "${now}: ${prev} ${next}"
done
A more concise form using a bash inline "ternary" expression:
[[ $(date +%w) == 1 ]] && days=3 || days=1
date -d "$days day ago" +"%Y-%m-%d"
Related
#!/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"
then
workday=Yes
nworkdays=$((nworkdays+1))
else
workday=
fi
done
[ "$workday" ] && [ "$nworkdays" -eq 6 ] && echo "$nworkdays $today $workday"
~
I wanted to execute the script but the script goes inside the loop and asks for user input.
Expected result
on execution display workday
Best Regards,
Shalini
As mentioned by #urbanespacemen kindly remove the grep command
#!/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 ]
then
workday=Yes
nworkdays=$((nworkdays+1))
else
workday=
fi
done
[ "$workday" ] && [ "$nworkdays" -eq 6 ] && echo "$nworkdays $today $workday"
Now should work
I'm struggling a bit on how to put the correct date in my shell script for a specific time range.
For instance i need to check if i'm in the correct range to generate some file based on date(12am - 3am )
so far I'm checking :
workflow_start_time=$(date -d "$(date +%Y-%m-%d) 23:00:00" +"%s")
scheduled_run_time=$workflow_start_time
if [ "$(date -d #${scheduled_run_time} +"%H")" -ge 23 ] && [ "$(date -d #${scheduled_run_time} +"%H")" -lt 2 ]; then
that is starting at 23 because i need to take into account 1 hour server difference, so this will start around 12 and should finish around 2am, which will be 3am.
any help here?
Convert date to timestamp.
toStamp() { date --date="$1" +%s; }
Check if date is between other dates.
# [$1, $2): bounds
# $3 current date
isBetween() {
[[ `toStamp $1` -le `toStamp $3` ]]&&\
[[ `toStamp $2` -gt `toStamp $3` ]]
}
or
isTimeStampBetween() {
[[ $1 -le $3 ]]&&\
[[ $2 -gt $3 ]]
}
if you have timestamps only.
An example to check if a date is between 2 other would be:
if $(isBetween 2012 2020 2013) ; then dosomething
You can include these functions in your file.
With following code I can roll day in Linux back and forth.
date -s 'tomorrow'
date -s 'yesterday'
I would like to do the same but skip weekends.
The following gives you next working day (for bash):
if [[ $( date +%u ) -eq 5 ]] ; then date --date="next Monday" ; else date --date="next day" ; fi
This script sets the day to the next weekday. Before forewarned that these scripts strip out the time of day when jumping over the weekend. Also, they are not portable to limited shells like busybox.
week_day=$(date +%w) #get the week day as a number from 0
if [[ $week_day == 5 || $week_day == 6 ]] #check to see if it is Fri or Sat
then date -s 'next monday' #if it is Fri or Sat, the set day to next monday
else date -s tomorrow #it is a different day of the week, go to the next day
fi
The last week day
week_day=$(date +%w) #get the week day as a number from 0 to 6 starting with 0 as Sunday
if [[ $week_day == 0 || $week_day == 1 ]] #check to see if it is Sun or Mon
then date -s 'last friday' #if it is Sun or Mon, the set day to last friday
else date -s yesterday #it is a different day of the week, go to yesterday
fi
if [[ $( date +%u ) = 5 ]] ; then date --set="+3 days" ; else date --set="+1 days" ; fi
if [[ $( date +%u ) = 1 ]] ; then date --set="-3 days" ; else date --set="-1 days" ; fi
If I give month and year as input the output should be dates of mondays and thrusdays of that month.
eg: If input is
year = 2013
month = 02
output should be
2013-02-04
2013-02-07
2013-02-11
2013-02-14
2013-02-18
2013-02-21
2013-02-25
2013-02-28
how to use date function for this in shell scripting?
This method requires only 2 call to date, the rest is just arithmetic
year=2013
month=2
last=$(date -d "$year-$month-1 + 1 month - 1 day" +%d)
wday=$(date -d "$year-$month-1" +%w)
for (( day=1; day<=$last; day++ )); do
if (( wday == 1 || wday == 4 )); then
printf "%4d-%02d-%02d\n" $year $month $day
fi
(( wday = (wday + 1) % 7 ))
done
2013-02-04
2013-02-07
2013-02-11
2013-02-14
2013-02-18
2013-02-21
2013-02-25
2013-02-28
year=2013
month=02
#Monday=1,Sunday=7
display_days="1 4"
for day in $(seq 1 31)
do
dow=$(date -d "$year-$month-$day" +%u 2>/dev/null)
for d in $display_days
do
if [ -z $dow ]; then continue; fi
if [ "$dow" -eq "$d" ]
then
date -d "$year-$month-$day" +%y-%m-%d
fi
done
done
Or just defer to ncal.
LC_ALL=C ncal "$#" | sed -n 's/\(Mo\|Th\)//p'
Weekdays are subject to localization so I added a C locale just in case.
Another way:
year=2013 month=02
cal $month $year |
sed '1,2d; s/^.. \(..\) .. .. \(..\).*/\1\n\2/' |
sed "/^ *$/d; s/^ /0/; s/^/$year-$month-/"
I want to check if the day is Sunday, but for some reason I can't get it to work.
[[ "date '+%a'" == "Sun" ]] && echo "Today is Sunday"
Use $(...) to execute a command and return the output as a string:
[[ $(date '+%a') == "Sun" ]]
You can use the date +%u to get the day number of the week... 1 - 7 with Monday being 1 that way you should not have an issue with non-english locales
[[ $(date '+%a') == "Sun" ]] && echo "Sunday!"
case "$(date '+%a')" in "Sun" ) echo "sunday";; esac
For completion:
If you have multiple locales I advise to use +%u cf. man date:
%u day of week (1..7); 1 is Monday
Today is monday:
date +%u
1
if [[ $(date +%u) -eq 1 ]]; then
echo 'ho no :c'
fi
ho no :c
hth