#!/bin/bash
#< Thorough date validation script - checks leap years too

PROGNAME=`basename $0`
MODE="UK"

function usage() {
 echo "Usage: ${PROGNAME} [-u] [dd|mm] [dd|mm] [yyyy]" >&2
}

case ${1} in
 '-u') MODE="US"
       shift
       ;;
esac

if [ "${#}" -ne "3" ]; then
  usage
fi

case ${MODE} in
 "UK") DAY="${1}"
       MONTH="${2}"
       YEAR="${3}"
       ;;
 "US") MONTH="${1}"
       DAY="${2}"
       YEAR="${3}"
       ;;
esac
DATE="${1} ${2} ${3}"

echo "${DAY}" | grep "^[0-9][0-9]$" >/dev/null 2>&1
if [ "${?}" -ne "0" ]; then
  echo "Error: ${DAY} not in DD format" >&2
  exit 1
fi

echo "${MONTH}" | grep "^[0-9][0-9]$" >/dev/null 2>&1
if [ "${?}" -ne "0" ]; then
  echo "Error: ${MONTH} is not in MM format" >&2
  exit 1
fi
if [ "${MONTH}" -gt "12" -o "${MONTH}" -lt "1" ]; then
  echo "Error: ${MONTH} is not a valid month!" >&2
  exit 1
fi

echo "${YEAR}" | grep "^[0-9][0-9][0-9][0-9]$" >/dev/null 2>&1
if [ "${?}" -ne "0" ]; then
  echo "Error: ${YEAR} is not in YYYY format" >&2
  exit 1
fi
if [ "${YEAR}" -lt "1950" -o "${YEAR}" -gt "2050" ]; then
  echo "Error: ${YEAR} not between 1950 and 2050 inclusive" >&2
  exit 1
fi

case ${MONTH} in
 01|03|05|07|08|09|10|12)
       if [ "${DAY}" -gt "31" -o "${DAY}" -lt "1" ]; then
          echo "Error: ${DAY} not a valid day" >&2
          exit 1
       fi
       ;;
 04|06|09|11)
       if [ "${DAY}" -gt "30" -o "${DAY}" -lt "1" ]; then
          echo "Error: ${DAY} not a valid day" >&2
          exit 1
       fi
       ;;
 02)   # Damn February ;-)
       if [ "$((YEAR % 4))" -ne "0" ]; then
          LEAP=1
       elif [ "$((YEAR % 400))" -eq "0" ]; then
          LEAP=0
       elif [ "$((YEAR % 100))" -eq "0" ]; then
          LEAP=1
       else
          LEAP=0
       fi
       if [ "${LEAP}" -eq "0" ]; then
           if [ "${DAY}" -gt "29" -o "${DAY}" -lt "1" ]; then
               echo "Error: ${DAY} not a valid day" >&2
               exit 1
           fi
       else
           if [ "${DAY}" -gt "28" -o "${DAY}" -lt "1" ]; then
               echo "Error: ${DAY} not a valid day" >&2
               exit 1
           fi
       fi
       ;;
esac

echo "${DATE} is a valid date!"

exit 0