Seeking help with date calculations in bash (on MacOS-X)
Linux - NewbieThis Linux forum is for members that are new to Linux.
Just starting out and have a question?
If it is not in the man pages or the how-to's this is the place!
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Note: spacing does matter in scripts; not everywhere, but it does matter in many cases.
By the way, you don't have to add the suffix ".sh", if the script has the "executable" flag set.
At this point it's clear that you're running your scripts on MacOS-X and the date command is quite different from the GNU date. Therefore, any suggestion to use date -d or date --date is not applicable. My advice is to stick with bash and do all the necessary calculations using "day" as units and taking into account leap years.
We didn't know you were trying to do all that on a Mac. Apparently, the date command is not the same on MacOS-X, as colucix already mentioned. Glad it worked in the end.
We didn't know you were trying to do all that on a Mac. Apparently, the date command is not the same on MacOS-X, as colucix already mentioned. Glad it worked in the end.
Yeah, I just now read the "Mac" subject line.
Has it been there all along, or was it changed?
I thought the subject was "Seeking help" yesterday?
I tend to power through stuff sometimes.
I really should drink de-caf.
well you have the right syntax for your date command now
But, you still have me out by 1 year
28-09-2000 should be 12, your script gets 13
For now.. lets not worry about that
So, you have todays date as seconds from epoch.. (1970-01-01 UTC)
and you have the birthdate, again in seconds BUT for this year!
good
(This years birthday in seconds ) - ( today in seconds ) = seconds until birthday
Now, if that is negative, go back and do again but add a year
then it is just a question of converting seconds to days, weeks, hours, mins even seconds!.
I wouldn't bother with months, since it just complicates things
so now you need to do the days until next birthday
just a note on "code style",
I see you are using tabs
I used to use tabs, but did some things in Android and they used a 4 space indent
using spaces may seem more effort, but as you can see in your code box, it often translates to be equivalent to 8 spaces, and can make things 'awkward'
so now you need to do the days until next birthday
just a note on "code style",
I see you are using tabs
I used to use tabs, but did some things in Android and they used a 4 space indent
using spaces may seem more effort, but as you can see in your code box, it often translates to be equivalent to 8 spaces, and can make things 'awkward'
ps: code style i started coding since 4 days so.........i am big noob
i still have a problem:
-if i put 28-06-1994 he gives me the correct result 19 years 274 days
-but if his birthday is tommorow so 28-09-1994 he gives me the good days but the age must be 18 and he gives me 19 can anyone help me?
ps2: SOLVED
Code:
string=$1
IFS=-
set $string
year=$3
mounth=$2
day=$1
an=`date +%Y`
luna=`date +%m`
zi=`date +%d`
difan=$(( $an-$year ))
if [ "$luna" -le "$mounth" ] && [ "$zi" -lt "$day" ] || [ "$luna" -lt "$mounth" ]
then
difan2=$(( $difan-1 ))
else
difan2=$difan
fi
if [[ $an = $year && $luna < $mounth ]]
then
difan2=0
fi
if [[ $difan2 > 1 ]]
then
echo "Age : $difan2 ans"
else
echo "Age : $difan2 an"
fi
z1=`date -jf "%d-%m" $day-$mounth "+%s"`
z2=`date -jf "%d-%m" $zi-$luna "+%s"`
z3=$(($z1-$z2))
zile=$(( $z3/86400 ))
if [[ $zile < 0 ]]
then
zileb=$(($zile+365))
else
zileb=$zile
fi
if [[ $zile > 1 ]]
then
echo "Prochain anniversaire dans : $zileb jours"
else
echo "Prochain anniversaire dans : $zileb jour"
fi
Last edited by sparky90ful; 09-27-2013 at 04:51 AM.
OK, so here is how I did it ( see below )
Don't panic, I have been doing this a while
besides, probably has some bugs it it
I don't think it is 100% accurate, but close enough
obviously if after 4 days you submit that, questions will be asked
but maybe you can pull some bits from it
I've included some links for you to read
best if you read it in something with syntax highlighting
Code:
#!/usr/bin/env bash
# I don't know about macOSX , but the shabang above works with both Linux and FreeBSD
# however, some Linux distos may have env in a different PATH, which is a real pain
# NOTE: this script has no error checking !!!
#
string=$1
OrigIFS=$IFS
IFS=-
set $string
y=$3
m=$2
d=$1
IFS=$OrigIFS
# Figured the below was a nice easy test to figure out which date syntax to use
# http://www.tldp.org/LDP/abs/html/io-redirection.html
# note the redirection to /dev/null
# to stop pesky messages on screen ;)
date --date="$(date +%Y)" 2> /dev/null 1> /dev/null && OS=Linux || OS=BSD-MacOSX
#########
# The above is equivalent to this:
#
# if [[ $($date --date="$(date +%Y)" 2> /dev/null 1> /dev/null && OS=Linux || OS=BSD-MacOSX) ]]
# then
# OS=Linux
# else
# OS=BSD-MacOSX
# fi
########## http://www.tldp.org/LDP/abs/html/ops.html#ANDOR
# below is a function
# http://www.tldp.org/LDP/abs/html/functions.html
# I use three of them in this script
#
GetAge () {
case $OS in
Linux) SecondsSince=$(( $( date +%s ) - $( date +%s --date="${y}-${m}-${d}" ) ));;
BSD-MacOSX) SecondsSince=$(( $( date +%s ) - $( date -j -f "%Y-%m-%d_%H%M%S" "${y}-${m}-${d}_000000" "+%s" ) ));;
esac
# case http://www.tldp.org/LDP/abs/html/testbranch.html#EX29
# equivalent :
#
# if [[ "$OS" == "Linux" ]]
# then
# SecondsSince=$(( ...
# elif [[ "$OS" == "BSD-MacOSX" ]]
# then
# SecondsSince=$(( ...
#
####
HoursSince=$(( $SecondsSince / 3600 ))
Days=$(( $HoursSince / 24 ))
Years=$( awk '{print $1/365.242199}' <<< $Days )
# Not perfect.
# 365.242199 from
# http://www.timeanddate.com/date/leapyear.html
#
Remainder="0.${Years/*.}"
# above and below see http://www.tldp.org/LDP/abs/html/refcards.html#AEN22664
Years="${Years%.*}"
RemainderDays=$( awk '{printf "%d",365.242199*$1}' <<< $Remainder )
ThisYear=$(date +%Y)
printf "%21s" "Age : "
printf "$(s_suffix $Years year) $(s_suffix $RemainderDays day)\n"
########## ^ called the s_suffix function, ( bottom of script )
# gave it the Age ( actually, I should rename Years to AgeInYears ;) )
# and year ( as a string )
case $(( ${Years} + 1 )) in
1|*[2-9][1]) suffix="st";;
2|*[2-9][2]) suffix="nd";;
3|*[2-9][3]) suffix="rd";;
*) suffix="th";;
esac
# case again, with Regular expresion
while true;do
printf "%21s" "$(( ${Years} + 1 ))${suffix} Birthday in : "
CountDown
# ^ the below function
printf "%-10s" ""
# ^^ comment that out to see why it is there ;)
printf "\r"
sleep 1
done
}
# I shall let you look up while loops ;)
CountDown () {
case $OS in
Linux) SecondsToGo=$(( $( date +%s --date="${ThisYear}-${m}-${d}" ) - $( date +%s ) ));;
BSD-MacOSX) SecondsToGo=$(( $( date -j -f "%Y-%m-%d_%H%M%S" "${ThisYear}-${m}-${d}_000000" "+%s" ) - $( date +%s ) ));;
esac
(( $SecondsToGo < 0 )) && \
case $OS in
Linux) SecondsToGo=$(( $( date +%s --date="$((${ThisYear}+1))-${m}-${d}" ) - $( date +%s ) ));;
BSD-MacOSX) SecondsToGo=$(( $( date -j -f "%Y-%m-%d_%H%M%S" "$((${ThisYear}+1))-${m}-${d}_000000" "+%s" ) - $( date +%s ) ));;
esac
# take advantage of the 'rounding', go back and find the difference ;)
#
HoursToGo=$(( $SecondsToGo / 3600 ))
SecondsToGo=$(( $SecondsToGo - $(( $HoursToGo * 3600 )) ))
DaysToGo=$(( $HoursToGo / 24 ))
HoursToGo=$(( $HoursToGo - $(( $DaysToGo * 24 )) ))
WeeksToGo=$(( $DaysToGo / 7 ))
DaysToGo=$(( $DaysToGo - $(( $WeeksToGo * 7 )) ))
MinsToGo=$(( $SecondsToGo / 60 ))
SecondsToGo=$(( $SecondsToGo - $(( $MinsToGo * 60 )) ))
for Output in "$WeeksToGo week" "$DaysToGo day" "$HoursToGo hour" "$MinsToGo minute" "$SecondsToGo second";do
s_suffix $Output
done
# another loop to look at
#
}
s_suffix (){
# expects a number and a string
# if greater than 1 add an s to the end of the 'string'
# so week becomes weeks, day days and so on
# add if 0, print nothing
case $1 in
0) ;;
1) printf "${1} ${2} ";;
*) printf "${1} ${2}s ";;
esac
}
GetAge
# was fun :)
Maybe for you was fun but for me ...........yes i have a satisfaction so.......that's god but like i say i am coding since 4 days i didn't knew anything so now i strt with sell which is sooooooow hard to understand anyway for me is hard so thanks at all for your replays and i hope you will help me in future because now i have a project to make a data base with some functions so i didn't know from where to start.........but if someone have some hints plese tell me.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.