#!/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
Related
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.
#!/bin/bash
# slightly malformed input data
input_start=2014-11-1
input_end=2016-01-1
# After this, startdate and enddate will be valid ISO 8601 dates,
# or the script will have aborted when it encountered unparseable data
# such as input_end=abcd
startdate=$(date -I -d "$input_start") || exit -1
enddate=$(date -I -d "$input_end") || exit -1
m="$startdate"
while [ "$m" != "$enddate" ]; do
echo $m
m=$(date -I -d "$m + 1 month")
done
"Script is running fine but when I want to change the While loop condition i.e '<=' 'less then or equal to' its giving error even I tried using "-le".What I want to do here is startdate <= enddate in while loop. Can anyone suggest what needs to done to overcome this issue.
Same Code
-le is for numeric data. 2014-11-01 is not a number. Use < or >. (You need to escape them as \< or \>. Or use [[ instead of [.)
effectively, change
while [ "$m" != "$enddate" ]; do
to
until [ "$m" \> "$enddate" ]; do
or
until [ "$m" '>' "$enddate" ]; do
or
until [[ "$m" > "$enddate" ]]; do
Alternately, use seconds since epoch instead of ISO8601 format.
while [ "$(date -d "$m" +%s)" -le "$(date -d "$enddate" +%s)" ]; do
With dateutils' datetest this is simple:
$ datetest 2014-11-1 --le 2016-01-1 ; echo $?
0
$ datetest 2014-11-1 --gt 2016-01-1 ; echo $?
1
Then again, what you want is simply done by dateseq, which also happens to be a tool of the dateutils suite.
$ dateseq 2014-11-1 +1mo 2016-01-1
2014-11-01
2014-12-01
2015-01-01
2015-02-01
2015-03-01
2015-04-01
2015-05-01
2015-06-01
2015-07-01
2015-08-01
2015-09-01
2015-10-01
2015-11-01
2015-12-01
2016-01-01
Disclaimer: I am the author of the package.
my ksh version is not allowed date -d.
The bellow code has problem when current month is January.
#!/bin/ksh
yy=`date +%Y`
mm=`date +%m-1|bc`
[ $mm -lt 1 ] && (mm=12;yy=`expr $yy - 1`)
[ $mm -le 9 ] && mm="0$mm"
getcal=`cal $mm $yy`
last_dd=`echo $getcal|awk '{print $NF}'`
dd1=`echo $getcal|awk '{print $10}'`
first_dd="0$dd1"
echo $yy$mm$last_day
echo $yy$mm$first_day
You're using a subshell: any variable changes you make will not survive the subshell exiting:
$ m=5; (m=10); echo $m
5
Use a different grouping construct
[ $mm -lt 1 ] && { mm=12; ((yy -= 1)); }
If you have GNU date, you can do:
$ first_of_this_month=$(date "+%Y-%m-01")
$ date -d "$first_of_this_month - 1 day" "+%Y-%m-%d"
2014-03-31
$ date -d "$first_of_this_month - 1 month" "+%Y-%m-%d"
2014-03-01
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 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"