Simon Blackbourn
Simon Blackbourn

Reputation: 278

Bash script: Checking today's date against a date without year

I'd like to send a renewal reminder email out four weeks before an expiry date. I'm storing all the details in an array, but I can't figure out how I check if today's date is 28 days before the date in the array.

Here's what I've got so far, any help with how to do the date checking would be much appreciated:

#!/bin/sh

adminemail="[email protected]"

account[1]="June 03|[email protected]|John"
account[2]="April 17|[email protected]|Jane"
account[3]="November 29|[email protected]|Sarah"

for check in "${account[@]}"
do
    renew=$(echo $check | cut -f1 -d\|)
    email=$(echo $check | cut -f2 -d\|)
    name=$(echo $check | cut -f3 -d\|)

    # check date is 28 days away
    if [ ?????? ]
    then
        subject="Your account is due for renewal"
        text="
Dear $name,

Your account is due for renewal by $renew. blah blah blah"

        echo "$text" | mail -s "$subject" $email -- -r $adminemail
    fi
done

Upvotes: 1

Views: 5057

Answers (2)

James
James

Reputation: 4737

You can get the month and date of 28 days before the check date like this:

warning_date=$(date --date='June 03 -28 days' +%s)

The current date in the same format:

current_date=$(date +%s)

Since they are both numeric and in the same scale (seconds since epoch), now you can check if $current_date is greater than $warning_date:

if [ $warning_date -lt $current_date ]; then
  # ...
fi

Put it all together now:

# ...
current_date=$(date +%s)

for check in ${account[@]}; do
  # ...
  renew=$(echo $check | cut -f1 -d\|)

  # 28 days before the account renewal date
  warning_date=$(date --date="$renew -28 days" +%m%d)

  if [ $warning_date -lt $current_date ]; then
    # Set up your email and send it.
  fi
done

Update

To be reminded only if current date is the 28th day prior to the check date you can get each date in the same month date format and compare for string equality:

# ...
current_date=$(date "+%B %d")

for check in ${account[@]}; do
  # ...
  renew=$(echo $check | cut -f1 -d\|)

  # The 28th day before the account renewal day
  warning_date=$(date --date="$renew -28 days" "%B %d")

  if [ $warning_date == $current_date ]; then
    # Set up your email and send it.
  fi
done

Upvotes: 4

chepner
chepner

Reputation: 531075

It's best to use Unix timestamps for date comparisons, as they are simple integers.

#!/bin/bash

adminemail="[email protected]"

account[1]="June 03|[email protected]|John"
account[2]="April 17|[email protected]|Jane"
account[3]="November 29|[email protected]|Sarah"

for check in "${account[@]}"
do
    IFS="|" read renew email name <<< "$check"

    # GNU date assumed. Similar commands are available for BSD date
    ts=$( date +%s --date "$renew" )
    now=$( date +%s )
    (( ts < now )) && (( ts+=365*24*3600 )) # Check the upcoming date, not the previous

    TMINUS_28_days=$(( ts - 28*24*3600 ))
    TMINUS_29_days=$(( ts - 29*24*3600 ))
    if (( TMINUS_29_days < now && now <  TMINUS_28_days)); then        
        subject="Your account is due for renewal"
        mail -s "$subject" "$email" -- -r "$adminemail" <<EOF
Dear $name,

Your account is due for renewal by $renew. blah blah blah
EOF    
    fi
done

Upvotes: 3

Related Questions