Reputation: 27
How to validate the date in Unix
.
Where the date format is DD-MM-YYYY
.
For example if i run one script ./ValidateDate.sh DD-MM-YYYY
then it should check that the date is in this format and also that the date exists.
If date is valid and in above format then proceed for next else print message 'Invalid date'
Thanks.
Upvotes: 0
Views: 15238
Reputation: 107040
Well... This is a fine can o' worms.
Any shell script that you create may not work on all of the various flavors of Unix/Linux.
The BSD date command (found on OS X and Solaris) does a great job at taking in the date and verifying the format. It requires you to specify your date format, but once you do, it has no problems:
if date -j -f "%d-%m-%Y" "$DATE" 2>&1 > /dev/null # No output
then
echo "ERROR: Date '$DATE' is not a valid format."
exit 2
else
echo "Date is '$DATE'."
fi
Linux and other systems that use GNU's date can also validate the date, but use a different syntax:
date -d "$DATE" 2>&1 /dev/null # With a bit of luck this will work...
if $? -ne 0
then
echo "ERROR: Date '$DATE' is not a valid format."
else
echo "Date is '$DATE'."
fi
I say With a bit of luck because it's up to the date
command to figure out your date's format. This normally works, and will work with your YYYY-MM-DD
format, but it can be confusing:
Imagine this:
$ DATE="15/6/2014" # It's June 15, 2014
$ date -d "$DATE"
date: invalid date `15/6/2014' # Invalid?
That's because in my timezone, the dd/mm/yyyy
format isn't a valid format. In my timezone, the date should be mm/dd/yyyy
. To get around this you can use Wintermute's suggestion and format the date into ISO format before using GNU's date format.
A more universal possibility is to use Perl or Python to figure out if the date is correct:
if perl -mTime::Piece -e "Time::Piece->strptime(\"$DATE\", \"%Y-%m-%d\")" 2> /dev/null
then
echo "ERROR: Date '$DATE' is not a valid format."
else
echo "Date is '$DATE'."
fi
This Perl oneliner will return a non-zero error status if $DATE
isn't a valid date in %Y-%m-%d
format.
Upvotes: 3
Reputation: 531165
You can do this fairly easily if you are willing to break the validation into two steps. First, check that the string is in the right format:
date=$1
[[ $date =~ ([0-9][0-9])-([0-9][0-9])-([0-9]+) ]] || { printf "Invalid date format\n"; exit 1; }
If that test passes, you can extract the day, month, and year fields, then verify that each falls in the correct range.
day=${BASH_REMATCH[1]}
month=${BASH_REMATCH[2]}
year=${BASH_REMATCH[3]}
thirty_one_days='0[1-9]|[12][0--9]|3[01]'
thirty_days='0[1-9]|[12][0--9]|30'
twenty_eight_days='0[1-9]|1[0-9]|2[0-8]'
case $month in
01|03|05|07|08|10|12)
[[ $day =~ $thirty_one_days ]] ;;
04|06|09|11)
[[ $day =~ $thirty_days ]] ;;
02)
# 1-28, but 29 OK in a leap year.
[[ $day =~ $twenty_eight_days ]] ||
(( year % 4 == 0 && $year % 400 == 0 && day == 29 ))
*)
false
esac || { print "Invalid date\n"; exit 1; }
Upvotes: 0
Reputation:
awk way
awk 'split($0,a,"-"){print strftime("%d-%m-%Y",mktime(a[3]" "a[2]" "a[1]" 00 00 00"))==$0?"valid":"not valid"}' <<< "31-12-1992"
It Converts the string to epoch,converts epoch back then checks against the original.
Edit:
Thought i would add after testing this works for dates
FROM 01-01-0
TO 31-12-2147483647
Although a drawback is after you go below the year 1000 you have to remove leading zeros from the year.
Upvotes: 0
Reputation: 44043
You can validate the date with the date
utility, but you first have to transform the input into something it can understand. I suggest ISO representation (always). It could, for example, look like this:
#!/bin/sh
PATTERN='\([0-9]\{1,2\}\)-\([0-9]\{1,2\}\)-\([0-9]\+\)'
# if the pattern doesn't match, this will give date an empty string, so it will fail as expected.
if date -d $(echo "$1" | sed -n "/$PATTERN/ { s/$PATTERN/\3-\2-\1/; p }") > /dev/null 2>&1 ; then
echo valid
else
echo invalid
fi
Upvotes: 0