问题
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
impliesend = '21/09/2017'
<date = '26/09/2017'
, but still I get anok
.- I use
date < “$end”
but I wantdate ≤ “$end”
How to correct 1 and 2?
回答1:
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 thedate
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 usesnow
andend
, not$now
and$end
: the((.))
arithmetic comparison interprets variable names as the integer value stored in the variable. Anyway, using dates, even inYYYYmmdd
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
andend
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.
回答2:
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 ...
回答3:
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).
来源:https://stackoverflow.com/questions/46426691/compare-two-dates-in-bash-in-mac-osx