Unix - get next saturday using cal command - shell

I need get te next saturday from starting the current date for create a file. For example, on linux:
date +%Y%m%d -d saturday
This return 20160430, the next saturday with current date 4/25/2016. That's I want.
I need the same result (or something like that) on Unix (SunOS 5.10). If I execute the same command, the return is the current date 20160425
There's another way to do that, for example using command cal? I tried but just return the first Saturday. The command:
cal | grep -v 2016 |grep -v Th | head -3 | head -1 | sed 's|^.*\([0-9]\)$|\1|g'
So, there's a way to get the next Saturday, starting from current date, using cal command?
Thanks for help!

You can obtain the day using following command:
cal -s | tail -n +2 | grep `date +%d` | cut -d' ' -f 7
Prints calendar of current month, starting weeks with Sunday, strips the year line, greps the line with today's date and gets its 7-th column, which is your Saturday month day number.
Now here is a little script that calculates the rest.
#!/bin/sh
TODAY=$(date +%d)
DAY=$(cal -s | tail -n +2 | grep ${TODAY} | cut -d' ' -f 7)
MONTH=$(date +%m)
YEAR=$(date +%Y)
if [[ $DAY -lt $TODAY ]]; then
# Saturday is next month
let MONTH=MONTH+1
if [[ $MONTH -eq 13 ]]; then
# Saturday is next year
let YEAR=YEAR+1
fi
fi
echo $YEAR$MONTH$DAY

Related

split date and time collide with space between them in bash

from my wp cli I receive a date format like this :
YYYY-mm-ddHH-mm-ss for example : 2020-02-2514:24:25
I would like to convert it to timestamp but the format date is incorrect.
I would like to split the date and time with space between them but I have no idea to do that currently.
with regex may be but I just seen how to replace space and I am a nooby with bash regex.
thank you for your help
Just use cut
root#a036fb1c94fa:~# DATE=$(echo "2020-02-2514:24:25" | cut -b-10)
root#a036fb1c94fa:~# TIME=$(echo "2020-02-2514:24:25" | cut -b11-)
root#a036fb1c94fa:~# TIMESTAMP=$(date -d "$DATE $TIME" +"%s")
root#a036fb1c94fa:~# echo $TIME
14:24:25
root#a036fb1c94fa:~# echo $DATE
2020-02-25
root#a036fb1c94fa:~# echo $TIMESTAMP
1582637065
Explanation:
echo "2020-02-2514:24:25" | cut -b-10
echo the string and cut it before the 10th byte
echo "2020-02-2514:24:25" | cut -b11-
echo the string and cut it from the 11th byte until the end
echo date -d "$DATE $TIME" +"%s"
give the right format to unix date command, with +"%s" to get its timestamp
You don't need any regex. You can select substrings in bash.
If the variable wpdate contains the string returned by wp cli, the corresponding timestamp can be put into the variable timestamp as follows:
timestamp=$(date '+%s' --date "${wpdate:0:10} ${wpdate:10:8}")
Explanation: ${wpdate:10:8} means the substring of wpdate starting at position 10 and containing 8 chars.

Using a Loop To Search Only Logs In A Time Window

I'm trying to find a pattern "INFO: Server startup in" for last 5 mins in a log file.
Here is the line from which I'm trying to find the pattern: "INFO | jvm 1 | main | 2018/07/09 00:11:29.077 | INFO: Server startup in 221008 ms"
The pattern is coming, but I need to shorten the code or create a loop for it.
I tried to create a loop, but it is not working. Here is my code without loops, which is working:
#!/bin/bash
#Written by Ashutosh
#We will declare variables with date and time of last 5 mins.
touch /tmp/a.txt;
ldt=$(date +"%Y%m%d");
cdt=$(date +"%Y/%m/%d %H:%M");
odtm5=$(date +"%Y/%m/%d %H:%M" --date "-5 min");
odtm4=$(date +"%Y/%m/%d %H:%M" --date "-4 min");
odtm3=$(date +"%Y/%m/%d %H:%M" --date "-3 min");
odtm2=$(date +"%Y/%m/%d %H:%M" --date "-2 min");
odtm1=$(date +"%Y/%m/%d %H:%M" --date "-1 min");
## Finding the pattern and storing it in a file
grep -e "$odtm1" -e "$cdt" -e "$odtm2" -e "$odtm3" -e "$odtm4" -e
"$odtm5" /some/log/path/console-$ldt.log
> /tmp/a.txt;
out=$(grep 'INFO: Server startup in' /tmp/a.txt);
echo "$out"
## remove the file that contains the pattern
rm /tmp/a.txt;
I have tried to use sed also, but date function is not working with it.
Can someone please give me the new changed script with loops?
Adopting your original logic:
time_re='('
for ((count=5; count>0; count--)); do
time_re+="$(date +'%Y/%m/%d %H:%M' --date "-$count min")|"
done
time_re+="$(date +'%Y/%m/%d %H:%M'))"
ldt=$(date +'%Y%m%d')
awk -v time_re="$time_re" '
$0 ~ time_re && /INFO: Server startup in/ { print $0 }
' "/some/log/path/console-$ldt.log"
Performance enhancements are certainly possible -- this could be made much faster by bisecting the log for the start time -- but the above addresses the explicit question (about using a loop to generate the time window). Note that it will get unwieldy -- you wouldn't want to use this to search for the last day, for example, as the regex would become utterly unreasonable.
Sounds like all you need is:
awk -v start="$(date +'%Y/%m/%d %H:%M' --date '-5 min')" -F'[[:space:]]*[|][[:space:]]*' '
($4>=start) && /INFO: Server startup in/
' file
No explicit loops or multiple calls to date required.
Here is a bash script that does the job (thanks to Charles for its improvement):
#!/bin/bash
limit=$(date -d '5 minutes ago' +%s)
today_logs="/some/log/path/console-$(date +'%Y%m%d').log"
yesterday_logs="/some/log/path/console-$(date +'%Y%m%d' -d yesterday).log"
tac "$today_logs" "$yesterday_logs" \
| while IFS='|' read -r prio jvm app date log; do
[ $(date -d "$date" +%s) -lt "$limit" ] && break
echo "|$jvm|$prio|$app|$date|$log"
done \
| grep -F 'INFO: Server startup in' \
| tac
It has the following advantages over your original script:
optimized: it parses log lines starting from the more recent ones and stops at the first line encountered that is more than 5 min old. At 23:59, no need to parse log lines from 0:00 to 23:53
arbitrary time window: you can replace "5 minutes" with "18 hours" and it will still work. A time window of more than one day needs adaptation since each day has it own log file
works correctly when day changes: at 0:00 the original script will never parse the log lines from 23:55:00 to 23:59:59
Mixing the above code with Ed Morton's answer, you get:
#!/bin/bash
limit=$(date -d '5 minutes ago' +'%Y/%m/%d %H:%M')
today_logs="/some/log/path/console-$(date +'%Y%m%d').log"
yesterday_logs="/some/log/path/console-$(date +'%Y%m%d' -d yesterday).log"
tac "$today_logs" "$yesterday_logs" \
| awk -v stop="$limit" -F'[[:space:]]*[|][[:space:]]*' '
($4 < stop) { exit }
/INFO: Server startup in/
' \
| tac

How can we get weekday based on given date in unix

From a given date in %m-%d-%Y format we should determine what day it is.
Example: for the date 09-01-2017 output should be Friday
Very simple. Just use the date command itself with correct options.
$ date -j -f '%m-%d-%Y' "09-01-2017" +'%A'
Friday
If you have your date like this:
d="09-01-2017"
you need to reformat it to "YYYY-MM-DD"
date -d $(echo $d|awk -F- '{print $3 "-" $1 "-" $2}') +%A # DOW
Here is what I usually do. I would use the date function.
you can do 'man date' and find options.
$ d=2020-08-20 \
$ date -d "$d" +%u \
4 \
$ date -d "$d" +%A \
Thursday
DayOfWeek=$(date +%A)
This would yield the day of week monday-sunday
If your input date is strictly in the format MM-DD-YYYY, use the following
IFS='-' read -ra ADDR <<< "09-01-2017"
formattedDate=${ADDR[2]}-${ADDR[0]}-${ADDR[1]}
date -d $formattedDate +%A
The first line tokenizes the components of the date and the second rearranges them
You can pass it as %m/%d%Y which gets recognized by the date command.
$ date --date="`echo 09-01-2017| sed -e 's/-/\//g' `" +'%A'
Friday
To verify it, pass %F to get it in ISO format
$ date --date="`echo 09-01-2017| sed -e 's/-/\//g' `" +'%A %F'
Friday 2017-09-01
date +%A
# let us see in a for loop
for i in {1..7}; do date +%A --date=+${i}day; done
Wednesday
Thursday
Friday
Saturday
Sunday
Monday
Tuesday

Shell Script for Yesterdays Date

I have tried adding -d "yesterday" but I haven't had any luck getting it to work. Here is what I have for the whole script:
#! /bin/bash
saveDir="TJ"
dd=$(date +"%m-%d-%Y")
for file in *.csv ; do
saveName="${saveDir}/TJ ${dd}.csv"
cut -d',' -f2,14 "$file" > "$saveName"
done
how do I get dd to output yesterdays date instead of the current date?
EDIT: This is what I have now
#! /bin/bash
saveDir="TJ"
dd=$(date --date='yesterday' +'%m-%d-%Y')
for file in *.csv ; do
saveName="${saveDir}/TJ ${dd}.csv"
cut -d',' -f2,14 "$file" > "$saveName"
done
the above is saving the file as TJ .csv but I'm not sure what was done incorrectly
I think you want to use -
$ cat test.sh
#!/bin/bash
dd=$(date --date='yesterday' +'%m-%d-%Y')
echo $dd
$ ./test.sh
12-31-2013
or you could use
$ date -d '1 day ago' +'%m-%d-%Y'
12/31/2013
And for tomorrow -
$ date -d '1 day' +'%m-%d-%Y'
01/02/2014
or
$ date --date='tomorrow'
Thu Jan 2 21:25:00 EST 2014
Get today's date in seconds since epoch. Subtract 86400 to get to yesterday. Then convert yesterday to the string format you want.
today=`date +"%s"`
yesterday=`expr $today - 86400`
dd=`date --date="#${yesterday}" +"%m-%d-%Y"`
Try this
yday=$(date --date yesterday "+%d-%m-%Y")
echo $yday
And If you works in Linux
yday=$(date -d "-1 days" +"%d-%m-%Y")
echo $yday
I tried date -d "yesterday" +%m-%d-%Y on my Linux, it worked fine.
If you are on unix platform, you cannot use -d,
you can get yesterday's date using perl, this is how I do using perl
dd=$(perl -e '($a,$b,$c,$day,$mon,$year,$d,$e,$f) = localtime(time-86400);printf "%02d-%02d-%4d",$day, $mon+1, $year+1900')
echo $dd
01-01-2014
NewDate=`date +"%A %d %B %Y" --date="-1 day"`
echo $NewDate
this will give your yesterday's date (-1)
This will give you tomorrow's date (+1)
even you can check for any values like (+/-) days

Get the date (a day before current time) in Bash

How can I print the date which is a day before current time in Bash?
if you have GNU date and i understood you correctly
$ date +%Y:%m:%d -d "yesterday"
2009:11:09
or
$ date +%Y:%m:%d -d "1 day ago"
2009:11:09
If you have BSD (OSX) date you can do it like this:
date -j -v-1d
Wed Dec 14 15:34:14 CET 2011
Or if you want to do date calculations on an arbitrary date:
date -j -v-1d -f "%Y-%m-%d" "2011-09-01" "+%Y-%m-%d"
2011-08-31
date --date='-1 day'
MAC OSX
For yesterday's date:
date -v-1d +%F
where 1d defines current day minus 1 day. Similarly,
date -v-1w +%F - for previous week date
date -v-1m +%F - for previous month date
IF YOU HAVE GNU DATE,
date --date="1 day ago"
More info: https://www.cyberciti.biz/tips/linux-unix-get-yesterdays-tomorrows-date.html
Sorry not mentioning I on Solaris system.
As such, the -date switch is not available on Solaris bash.
I find out I can get the previous date with little trick on timezone.
DATE=`TZ=MYT+16 date +%Y-%m-%d_%r`
echo $DATE
Well this is a late answer,but this seems to work!!
YESTERDAY=`TZ=GMT+24 date +%d-%m-%Y`;
echo $YESTERDAY;
Advanced Bash-scripting Guide
date +%Y:%m:%d -d "yesterday"
For details about the date format see the man page for date
date --date='-1 day'
date -d "yesterday" '+%Y-%m-%d'
or
date=$(date -d "yesterday" '+%Y-%m-%d')
echo $date
Use Perl instead perhaps?
perl -e 'print scalar localtime( time - 86400 ) . "\n";'
Or, use nawk and (ab)use /usr/bin/adb:
nawk 'BEGIN{printf "0t%d=Y\n", srand()-86400}' | adb
Came across this too ... insane!
/usr/bin/truss /usr/bin/date 2>&1 | nawk -F= '/^time\(\)/ {gsub(/ /,"",$2);printf "0t%d=Y\n", $2-86400}' | adb
date --date='-1 day'
Not very sexy but might do the job:
perl -e 'my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time - 86400);$year += 1900; $mon+= 1; printf ("YESTERDAY: %04d%02d%02d \n", $year, $mon, $mday)'
Formated from "martin clayton" answer.
You could do a simple calculation, pimped with an regex, if the chosen date format is 'YYYYMM':
echo $(($(date +"%Y%m") - 1)) | sed -e 's/99$/12/'
In January of 2020 it will return 201912 ;-)
But, it's only a workaround, when date does not have calculation options and other dateinterpreter options (e.g. using perl) not available ;-)
short answer (GNU format):
date +%Y-%m-%d -d "-2 day"
if you are using OSX, but you need create for GNU compatible, install coreutils first
brew install coreutils
then edit your profile with:
#gnu coreutils first
export PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH"
re-start your terminal, and now you able to use GNU format!
yesterday=`date -d "-1 day" %F`
Puts yesterday's date in YYYY-MM-DD format into variable $yesterday.
#!/bin/bash
OFFSET=1;
eval `date "+day=%d; month=%m; year=%Y"`
# Subtract offset from day, if it goes below one use 'cal'
# to determine the number of days in the previous month.
day=`expr $day - $OFFSET`
if [ $day -le 0 ] ;then
month=`expr $month - 1`
if [ $month -eq 0 ] ;then
year=`expr $year - 1`
month=12
fi
set `cal $month $year`
xday=${$#}
day=`expr $xday + $day`
fi
echo $year-$month-$day
DST aware solution:
Manipulating the Timezone is possible for changing the clock some hours. Due to the daylight saving time, 24 hours ago can be today or the day before yesterday.
You are sure that yesterday is 20 or 30 hours ago. Which one? Well, the most recent one that is not today.
echo -e "$(TZ=GMT+30 date +%Y-%m-%d)\n$(TZ=GMT+20 date +%Y-%m-%d)" | grep -v $(date +%Y-%m-%d) | tail -1
The -e parameter used in the echo command is needed with bash, but will not work with ksh. In ksh you can use the same command without the -e flag.
When your script will be used in different environments, you can start the script with #!/bin/ksh or #!/bin/bash. You could also replace the \n by a newline:
echo "$(TZ=GMT+30 date +%Y-%m-%d)
$(TZ=GMT+20 date +%Y-%m-%d)" | grep -v $(date +%Y-%m-%d) | tail -1
Try the below code , which takes care of the DST part as well.
if [ $(date +%w) -eq $(date -u +%w) ]; then
tz=$(( 10#$gmthour - 10#$localhour ))
else
tz=$(( 24 - 10#$gmthour + 10#$localhour ))
fi
echo $tz
myTime=`TZ=GMT+$tz date +'%Y%m%d'`
Courtsey Ansgar Wiechers
date +%Y:%m:%d|awk -vFS=":" -vOFS=":" '{$3=$3-1;print}'
2009:11:9

Resources