Reputation: 1971
I'm new to Bash, apologies in advance.
Set-up
I have a particular end date end
which depends on a particular starting date s
and a period length p
such that, end=s+p
.
Problem
I want to execute a command if and only if today's date is before or equal to the end date.
That is: execute command iff date ≤ end
.
Code
s='20/09/2017'
p='1'
end=$( date -j -v +"$p"d -f "%d/%m/%Y" "$s")
if [[ date < “$end” ]];
then
echo 'ok'
fi
There are 2 things not the way they should be,
p=1
implies end = '21/09/2017'
< date = '26/09/2017'
, but still I get an ok
.date < “$end”
but I want date ≤ “$end”
How to correct 1 and 2?
Upvotes: 2
Views: 3692
Reputation: 29403
Your:
end=$( date -j -v+"$p"d -f "%d/%m/%Y" "$s" )
does not produce what you expect:
echo "$end"
Thu Sep 21 14:40:54 CEST 2017
What you expect can be obtained with:
end=$( date -j -v+"$p"d -f "%d/%m/%Y" "$s" +"%d/%m/%Y" )
Your comparison:
if [[ date < “$end” ]]; then
does not behave as you think. date
is not expanded as the result of the invocation of the date
command. So, your comparison is a string comparison (<
in the [[.]]
conditional expression context) between string "date"
and string "Thu Sep 21 14:40:54 CEST 2017"
. You should use something like:
date=$( date )
if [[ "$date" < “$end” ]]; then
instead (but using date
as a variable name is probably not a very good idea).
As noticed by the other answers, the date format you chose is not the best for comparisons. So, combining the various fixes with the other wise suggestions, you could try something like:
s='20170920'
p='1'
end=$( date -j -v+"$p"d -f "%Y%m%d" "$s" +"%Y%m%d" )
now=$( date +"%Y%m%d" )
if (( now <= end )); then
echo 'ok'
fi
Note: if (( now <= end )); then
is an arithmetic comparison and it should work in this specific case. Note also that it uses now
and end
, not $now
and $end
: the ((.))
arithmetic comparison interprets variable names as the integer value stored in the variable. Anyway, using dates, even in YYYYmmdd
format, as if they were integers is not that clean. Using UNIX timestamps, which should be OK at least until year 2038, is probably cleaner:
s='20170920'
p='1'
end=$( date -j -v+"$p"d -f "%Y%m%d" "$s" +"%s" )
now=$( date +"%s" )
if (( now <= end )); then
echo 'ok'
fi
because here now
and end
are number of seconds since the Epoch, that is, true integers. Note, however, that the result could be different from that of the previous solution because you have now a one-second accuracy instead of one-day. Chose which one corresponds to your needs.
Upvotes: 2
Reputation: 158280
When you format the date like YYYYMMDD
you can simply use an alphanumeric comparison:
start=$(date +'%Y%m%d')
end=$(date +'%Y%m%d')
# -gt means greater than - for example.
# check `help test` to get all available operators
if [ $start -gt $end ] ; then ...
Upvotes: 6
Reputation: 249652
First you need to use a date format which is lexicographical, meaning the big units come first. I highly recommend the ISO standard YYYY-MM-DD or YYYYMMDD. Second, <=
can be written as -le
(less or equal).
Upvotes: 3