Age calculation program with completed months and days - bash

Good afternoon I have a program in bash to calculate the age by entering the data of the year, month and day of birth. But I would also like to calculate the completed months and days. What would be the conditions that I should add to my code. Please help
echo "Enter your year of birth"
read a_nac
echo "Enter your month of birth"
read m_nac
echo "Enter your day of birth"
read d_nac
echo "-----------Birth Date---------"
echo $d_nac $m_nac $a_nac
a_act=$(date +%Y)
m_act=$(date +%m)
d_act=$(date +%d)
echo "-----------Current Date-------------"
echo $d_act $m_act $a_act
let edad=$a_act-$a_nac
if [ $m_act -lt $m_nac ]; then
((edad--))
elif [ $m_nac -eq $m_act -a $d_act -lt $d_nac ]; then
((edad--))
fi
echo "-----------Age-------------------"
echo "You have" $edad "years"

It's a bit complex to find a generic solution. For the dates after the epoch we can convert both the dates with date +%s and make a plain subtraction.
A more generic solution follows:
echo "Enter your year of birth"
read a_nac
echo "Enter your month of birth"
read m_nac
echo "Enter your day of birth"
read d_nac
echo "-----------Birth Date---------"
echo $d_nac $m_nac $a_nac
a_act=$(date +%Y)
m_act=$(date +%-m)
d_act=$(date +%-d)
echo "-----------Current Date-------------"
echo $d_act $m_act $a_act
let years=$a_act-$a_nac
if [ $m_act -lt $m_nac ]; then
((years--))
let months=$m_nac-$m_act
elif [ $m_act -ge $m_nac ]; then
let months=$m_act-$m_nac
elif [ $m_nac -eq $m_act -a $d_act -lt $d_nac ]; then
((years--))
fi
if [ $d_act -lt $d_nac ]; then
((months--))
let days=30-$d_nac+$d_act
else
let days=$d_act-$d_nac
fi
echo "-----------Age-------------------"
echo "You have $years years, $months months, $days days"
The line
let days=30-$d_nac+$d_act
does not take into account that not all the months have 30 days and the case of leap months. The correction is left to the reader ;)

Related

Printing date range in AIX

I'm trying to print date range in AIX. I'm not able to use 'date' in AIX properly. I've tried some solutions suggested in Stack overflow. Nothing worked. Please find the error and code below.
I can't download 'GNU'.
#!/bin/ksh
startdate=20141030
enddate=20141120
loop_date=$startdate
let j=0
while [ "$loop_date" -ne "$enddate" ]; do
loop_date=`date -j -v+${j}d -f "%Y%m%d" "$startdate" +"%Y%m%d"`
echo $loop_date
let j=j+1
done
Error:
date: illegal option -- j
Usage: date [-u] [+Field Descriptors]
Try this;
#!/bin/ksh
startdate=$1
enddate=$2
loop_date=$startdate
currentdate=`date +%Y%m%d`
let j=0;
if [[ $startdate -lt $currentdate && $enddate -lt $currentdate ]];then
loop_date=$currentdate
while [[ "$loop_date" -gt "$startdate" ]]; do
loop_date=$(TZ=CST+$j date +%Y%m%d)
if [[ $loop_date -le $enddate ]];then
echo $loop_date
fi
let j=j+24
done
fi
if [[ $startdate -gt $currentdate && $enddate -gt $currentdate ]];then
while [[ "$loop_date" -lt "$enddate" ]]; do
loop_date=$(TZ=CST-$j date +%Y%m%d)
if [[ $startdate -le $loop_date ]];then
echo $loop_date
fi
let j=j+24
done
fi
user#host:/tmp:>ksh test.sh 20150630 20150705
20150705
20150704
20150703
20150702
20150701
20150630
user#host:/tmp:>ksh test.sh 20170630 20170705
20170630
20170701
20170702
20170703
20170704
20170705

Why is my If Statement in Bash not working?

Hi I'm creating an archiving system in bash with a long and messy if statement which doesn't currently work with the current errors being on the last few lines with the else if statement. Although I expect there are further errors with this statement anyway. The variable choice is from a menu which displays in the terminal. So if they select option 1 the user then has to enter data to be written to the crontab file.
if [ $choice -eq "1" ] then
echo "Enter the MINUTE"
read minute
if [ $minute -eq 0 ] then
GLOBIGNORE=*
minute="*"
echo minute
fi
echo "Enter the Hour"
read hour
if [ $hour -eq 0 ] then
GLOBIGNORE=*
hour="*"
echo hour
fi
echo "Enter the Day"
read day
if [ $day -eq 0 ] then
GLOBIGNORE=*
day="*"
echo day
fi
echo "Enter the Month"
read month
if [ $month -eq 0 ] then
GLOBIGNORE=*
month="*"
echo month
fi
echo "Enter the weekday"
read weekday
if [ $weekday -eq 0 ] then
GLOBIGNORE=*
weekday="*"
echo weekday
fi
echo $minute $hour $day $month $weekday " date > ~/testcron.log" > testcron.txt fi
elif [ $choice -eq "2" ]
then
echo "Enter the Source and Destination Locations"
fi
There are several issues with your code:
if [ $hour -eq 0 ] then
GLOBIGNORE=*
hour="*"
echo hour
fi
In general (all test []) are missing a ; after it:
if [ $hour -eq 0 ]; then
The echo hour will not print the value of var hour but the word hour. Change to echo "$hour" (yes, quoted). Also, there is no need to set the variable GLOBIGNORE to * if vars are properly quoted.
The vars here are not quoted, that is a reason for it to fail (or to need GLOBIGNORE):
echo $minute $hour $day $month $weekday
Change to:
echo "$minute $hour $day $month $weekday"
The redirection on that same line is a plain >, that will empty the file.
If you want to append to the files, do as this:
echo "$minute $hour $day $month $weekday" "$(date >> ~/testcron.log)" >>testcron.txt
In that line there is an unneeded additional fi
This script may be of help:
get(){
read -p "$1" "$2"
if [ "$((${!2}))" -eq 0 ]; then
eval "$2"="*"
echo "${!2}"
fi
}
read -p "Choice?:" choice
if [ "$choice" -eq "1" ]; then
get "Enter the MINUTE" minute
get "Enter the Hour" hour
get "Enter the Day" day
get "Enter the Month" month
get "Enter the weekday" weekday
date >> ~/testcron.log
echo "$minute $hour $day $month $weekday" >> testcron.txt
elif [ "$choice" -eq "2" ]; then
echo "Enter the Source and Destination Locations"
fi
You are missing a semi-colon:
if [ $choice -eq "1" ]; then
or
if [ $choice -eq "1" ]
then
A semi-colon or a newline is required because the command is actually [ and has to be terminated after the ], which is just the last argument given to [.
That is the old test (or [) syntax, you could also use:
if (( choice == 1 ))
then

Comparing string read from csv file

I'm trying to compare string read from csv file in if condition. Below is the sample code I have written:
export IFS="~"
while read a b c
do
echo "line Num:$a"
if [ "$b"=="sat" ];then
echo "Its saturday"
echo $c
elif [ "$b"=="sun" ];then
echo "Its sunday"
echo $c
else
echo "Its weekday"
echo $c
fi
done < "$1"
Below is the csv file:
1~sat~enjoy
2~sun~enjoy
3~mon~work
4~tue~work
5~sun~enjoy
Below is the output I'm getting:
line Num:1
Its saturday
enjoy
line Num:2
Its saturday
enjoy
line Num:3
Its saturday
enjoy
line Num:4
Its saturday
enjoy
line Num:5
Its saturday
enjoy
Needed the below output instead:
line Num:1
Its saturday
enjoy
line Num:2
Its sunday
enjoy
line Num:3
Its weekday
work
line Num:4
Its weekday
work
line Num:5
Its sunday
enjoy
Any idea how to achieve this?
try
export IFS="~"
while read a b c
do
echo "line Num:$a"
if [ "$b" = "sat" ];then
echo "Its saturday"
echo $c
elif [ "$b" = "sun" ];then
echo "Its sunday"
echo $c
else
echo "Its weekday"
echo $c
fi
done < "$1"
do not use "$foo"=="$bar" as bash will only see one token.
you can also try
case "$b" in
sat) echo "It's saturday" ;;
sun) echo "It's sunday" ;;
*) echo "It's weekday" ;;
esac
echo $c

Test the date format to make sure it has been input correctly

I'm trying to write a test in bash that will check that a date has been entered correctly (or that a date has been entered at all). Here is what I'm trying to do:
tDate=$(lastCOB)
tDateOkay=0
until [ $tDateOkay -eq 1 ] ; do
read -p "Please Enter date for search. Use format: Date (YYYYMMDD): " -e -i "$tdate" tDate
if [[ -z "$tDate" || {check for valid YYMMDD format}]] ; then
echo "Invalid date. Please enter date in the correct format."
elif [[ $tDate -gt $(today)|| $tdate -eq $(today) ]] ; then
echo "Date must be in the past. Please try again."
else
tDateOkay=1
fi
done
The date has to be in the past and has to be written in the correct format, or the data won't be pulled from the correct folder. Thanks.
# other stuff
elif (( `date +%s -d $tDate` >= `date +%s` ))
then
echo 'Date must be in the past. Please try again.'
# other stuff

Shell script that calculates the previous Monday, Tuesday,... relative to today

I'm trying desperatly to find a bash or ksh routine that allows me to find for example the previous Monday,Tuesday,Wednesday,... preceding today's date. Additonal it has to work on plain vanilla Solaris X and I don't have the GNU date available.
eg: Today = Thursday 2013/01/17 ; Let's say I want to find the last Monday. It has to return:
2013/01/14
I've managed to find a script on the net that does the job perfectly for all days except in this specific case:
eg: Today = Thursday 2013/01/17 ; I want to find the last Thursday which should give as result: 2013/01/10 ; but instead I get todays date again.
The script used was this:
#!/bin/ksh
#Get the nbr of the current weekday (1-7)
DATEWEEK=`date +"%u"`
#Which previous weekday will we need (1-7)
WEEKDAY=$1
# Main part
#Get current date
DAY=`date +"%d"`
MONTH=`date +"%m"`
YEAR=`date +"%Y"`
#Loop trough the dates in the past
COUNTER=0
if [[ $DATEWEEK -eq $WEEKDAY ]] ; then
# I need to do something special for the cases when I want to find the date of the same day last week
DAYS_BACK=168
DAY=`TZ=CST+$DAYS_BACK date +%d`
echo "DAY (eq) = $DAY"
else
while [[ $DATEWEEK -ne $WEEKDAY ]] ; do
COUNTER=`expr $COUNTER + 1`
echo "Counter is: $COUNTER"
DAYS_BACK=`expr $COUNTER \* 24`
echo "DAYS BACK is: $DAYS_BACK"
DAY=`TZ=CST+$DAYS_BACK date +%d`
echo "DAY is: $DAY"
if [[ "$DAY" -eq 0 ]] ; then
MONTH=`expr "$MONTH" - 1`
if [[ "$MONTH" -eq 0 ]] ; then
MONTH=12
YEAR=`expr "$YEAR" - 1`
fi
fi
DATEWEEK=`expr $DATEWEEK - 1`
if [[ $DATEWEEK -eq 0 ]]; then
DATEWEEK=7
fi
done
fi
echo $DAY/$MONTH/$YEAR
(My previous suggestion didn't work as I thought. It was late last night ...)
The key thing is to ignore today, but still loop. Try it like this:
#!/bin/ksh
#Get the nbr of the current weekday (1-7)
DATEWEEK=`date +"%u"`
#Which previous weekday will we need (1-7)
WEEKDAY=$1
# Main part
#Get current date
DAY=`date +"%d"`
MONTH=`date +"%m"`
YEAR=`date +"%Y"`
#Loop trough the dates in the past
COUNTER=0
while [ $COUNTER -eq 0 ] || [[ $DATEWEEK -ne $WEEKDAY ]] ; do
COUNTER=`expr $COUNTER + 1`
echo "Counter is: $COUNTER"
DAYS_BACK=`expr $COUNTER \* 24`
echo "DAYS BACK is: $DAYS_BACK"
DAY=`TZ=CST+$DAYS_BACK date +%d`
echo "DAY is: $DAY"
if [[ "$DAY" -eq 0 ]] ; then
MONTH=`expr "$MONTH" - 1`
if [[ "$MONTH" -eq 0 ]] ; then
MONTH=12
YEAR=`expr "$YEAR" - 1`
fi
fi
DATEWEEK=`expr $DATEWEEK - 1`
if [[ $DATEWEEK -eq 0 ]]; then
DATEWEEK=7
fi
done
echo $DAY/$MONTH/$YEAR
Your DAY=`TZ=CST+$DAYS_BACK date +%d` trick doesn't work for me though. Linux date seems to cap it at one day.
Does this work?
today=$(date +"%u")
weekday=$1
curdate=$(date +"%s")
gobackdays=$(($today - $weekday))
if [ $gobackdays -le 0 ]; then
let gobackdays+=7
fi
SECSDAY=86400
backtime=$(($curdate - $gobackdays * $SECSDAY))
echo $(date -d "#$backtime")

Resources