Compare two dates in Bash in MAC OSX

左心房为你撑大大i 提交于 2021-01-04 06:58:27

问题


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,

  1. p=1 implies end = '21/09/2017' < date = '26/09/2017', but still I get an ok.
  2. I use date < “$end” but I want date ≤ “$end”

How to correct 1 and 2?


回答1:


  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" )
    
  2. 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).

  3. 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.




回答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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!