Reputation: 377
I have to create a Shell Script wherein one of the parameters will be the date in the format dd/mm/yyyy. My question is, how can I check if the Date passed as parameter really follows this Date Format? I tried to use the grep command as below:
if echo "$1" | grep -q '^[0-3][0-9]/[0-1][0-9]/[0-9]\{4\}$'
but it didn't give the correct format because the day for example can be 33, 34, (...), that is not really the correct format. Anyone know something that can really check if the date passed really follows the format dd/mm/yyyy ?
Upvotes: 19
Views: 102571
Reputation: 1
Another regex to validate the date:
"$1" =~ [0-9]{4}/(0[1-9]|1[0-2])/(0[1-9]|[1-2][0-9]$|3[0-1]$)
This regex has some shortcomings, it doesn't check if the day of month is valid for the specified month.
Upvotes: 0
Reputation: 11
I would like to give an extended answer for a slightly different format, but this can easily be changed to the dd/mm/YY format with the answers already given; it's tested on busybox (posix shell)
This is one of the first hits for web searches similar to "busybox posix shell script date" and "test format" or "validate" etc, so here my solution for busybox (tested with 1.29.3, 1.23.1)
#!/bin/sh
##########
#
# check if date valid in busybox
# tested in busybox 1.29.3, 1.23.1
#
# call with:
# $0 <yyyymmdd>
#
##########
mydate=$1
if echo $mydate | grep -qE '20[0-9][0-9](0[1-9]|1[0-2])([012][0-9]|3[01])'; then
printf 'may be valid\n'
date +%Y%m%d -d $mydate -D %Y%m%d > /dev/null 2>&1
is_valid=$?
if [ $is_valid -ne 0 ]; then
printf 'not valid\n'
return 1
else
mytestdate=$(date +%Y%m%d -d $mydate -D %Y%m%d)
if [ $mydate -ne $mytestdate ]; then
printf 'not valid, results in "%s"\n' "$mytestdate"
return 1
else
printf 'valid\n'
fi
fi
else
printf 'not valid (must be: <yyyymmdd>)\n'
return 1
fi
as in busybox (1.29.3 & 1.23.1) you have responds like:
lxsys:~# date +%Y%m%d -d 20110229 -D "%Y%m%d"
20110301
I had the need to validate the date in some better way but i wanted to rely mostly on the system itself
so with
mytestdate=$(date +%Y%m%d -d $mydate -D %Y%m%d)
if [ $mydate -ne $mytestdate ]; then
...
fi
there is a second test - do we have a difference between the wanted or given format (input, $mydate
) and the system interpretation (output, $mytestdate
) of it ... if it's not the same, discard the date
Upvotes: 1
Reputation: 3653
Use date
date "+%d/%m/%Y" -d "09/99/2013" > /dev/null 2>&1
is_valid=$?
The date string must be in "MM/DD/YYYY" format.
If you do not get 0 then date is in invalid format.
Upvotes: 30
Reputation: 61
This function expects 2 strings,a format string, a date string
The format string uses the codes from the date command but does not include the '+'
The function returns 0 if the provided date matches the given format, otherwise it returns 1
Code (my_script.sh)
#!/bin/bash
datecheck() {
local format="$1" d="$2"
[[ "$(date "+$format" -d "$d" 2>/dev/null)" == "$d" ]]
}
date_test="$1"
echo $date_test
if datecheck "%d %b %Y" "$date_test"; then
echo OK
else
echo KO
fi
Output
$ ./my_script.sh "05 Apr 2020"
05 Apr 2020
OK
$ ./my_script.sh "foo bar"
foo bar
KO
Upvotes: 6
Reputation: 51
Though the solution (if [[ $1 =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]] && date -d "$1" >/dev/null 2>&1) of @https://stackoverflow.com/users/2873507/vic-seedoubleyew is best one at least for linux, but it gives error as we can not directly compare/match regex in if statement. We should put the regex in a variable and then we should compare/match that variable in if statement. Moreover second part of if condition does not return a boolean value so this part will also cause error.
So I have done slight modification in the above formula and this modification can also be customized further for various other formats or combination of them.
DATEVALUE=2019-11-12
REGEX='^[0-9]{4}-[0-9]{2}-[0-9]{2}$'
if [[ $DATEVALUE =~ $REGEX ]] ; then
date -d $DATEVALUE
if [ $? -eq 0 ] ; then
echo "RIGHT DATE"
else
echo "WRONG DATE"
fi
else
echo "WRONG FORMAT"
fi
Upvotes: 0
Reputation: 7563
I wrote this bash script to validate date. I can accept mont as alphanumeric.
#!/bin/bash
function isDateValid {
DATE=$1
if [[ $DATE =~ ^[0-9]{1,2}-[0-9a-zA-Z]{1,3}-[0-9]{4}$ ]]; then
echo "Date $DATE is a number!"
day=`echo $DATE | cut -d'-' -f1`
month=`echo $DATE | cut -d'-' -f2`
year=`echo $DATE | cut -d'-' -f3`
if [ "$month" == "01" ] || [ "$month" == "1" ]; then
month="Jan"
elif [ "$month" == "02" ] || [ "$month" == "2" ]; then
month="Feb"
elif [ "$month" == "03" ] || [ "$month" == "3" ]; then
month="Mar"
elif [ "$month" == "04" ] || [ "$month" == "4" ]; then
month="Apr"
elif [ "$month" == "05" ] || [ "$month" == "5" ]; then
month="May"
elif [ "$month" == "06" ] || [ "$month" == "6" ]; then
month="Jun"
elif [ "$month" == "07" ] || [ "$month" == "7" ]; then
month="Jul"
elif [ "$month" == "08" ] || [ "$month" == "8" ]; then
month="Aug"
elif [ "$month" == "09" ] || [ "$month" == "9" ]; then
month="Sep"
elif [ "$month" == "10" ]; then
month="Oct"
elif [ "$month" == "11" ]; then
month="Nov"
elif [ "$month" == "12" ]; then
month="Dec"
fi
ymd=$year"-"$month"-"$day
echo "ymd: "$ymd
dmy=$(echo "$ymd" | awk -F- '{ OFS=FS; print $3,$2,$1 }')
echo "dmy: "$dmy
if date --date "$dmy" >/dev/null 2>&1; then
echo "OK"
return 0
else
echo "NOK"
return 1
fi
else
echo "Date $DATE is not a number"
return 1
fi
}
if isDateValid "15-15-2014"; then
echo "date is valid =)"
else
echo "bad format date"
fi
echo "==================="
if isDateValid "15-12-2014"; then
echo "date is valid =)"
else
echo "bad format date"
fi
echo "==================="
if isDateValid "15-Dec-2014"; then
echo "date is valid =)"
else
echo "bad format date"
fi
echo "==================="
if isDateValid "1-May-2014"; then
echo "date is valid =)"
else
echo "bad format date"
fi
echo "==================="
if isDateValid "1-1-2014"; then
echo "date is valid =)"
else
echo "bad format date"
fi
echo "==================="
if isDateValid "12-12-2014"; then
echo "date is valid =)"
else
echo "bad format date"
fi
Upvotes: 0
Reputation: 10526
The simplest solution, that still works perfectly, is the following :
if [[ $1 =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]] && date -d "$1" >/dev/null 2>&1
...
It consists in combining 2 checks :
$1
is of this format : NNNN-NN-NN
You need the two checks because :
date
will exit with code 0 even if your variable is a valid date in another format2016-13-45
Upvotes: 19
Reputation: 11
`X="2016-04-21" then check for the below value being 1 or 0.
cal echo $x | cut -c 6-7
echo $x | cut -c 1-4
2>/dev/null | grep -c echo $x | cut -c 9-10
If the value is 1, then it's valid, else it's not valid.
Upvotes: 1
Reputation: 19
#! /bin/bash
isDateInvalid()
{
DATE="${1}"
# Autorized separator char ['space', '/', '.', '_', '-']
SEPAR="([ \/._-])?"
# Date format day[01..31], month[01,03,05,07,08,10,12], year[1900..2099]
DATE_1="((([123][0]|[012][1-9])|3[1])${SEPAR}(0[13578]|1[02])${SEPAR}(19|20)[0-9][0-9])"
# Date format day[01..30], month[04,06,09,11], year[1900..2099]
DATE_2="(([123][0]|[012][1-9])${SEPAR}(0[469]|11)${SEPAR}(19|20)[0-9][0-9])"
# Date format day[01..28], month[02], year[1900..2099]
DATE_3="(([12][0]|[01][1-9]|2[1-8])${SEPAR}02${SEPAR}(19|20)[0-9][0-9])"
# Date format day[29], month[02], year[1904..2096]
DATE_4="(29${SEPAR}02${SEPAR}(19|20(0[48]|[2468][048]|[13579][26])))"
# Match the date in the Regex
if ! [[ "${DATE}" =~ "^(${DATE_1}|${DATE_2}|${DATE_3}|${DATE_4})$" ]]
then
echo -e "ERROR - '${DATE}' invalid!"
else
echo "${DATE} is valid"
fi
}
echo
echo "Exp 1: "`isDateInvalid '12/13/3000'`
echo "Exp 2: "`isDateInvalid '12/11/2014'`
echo "Exp 3: "`isDateInvalid '12 01 2000'`
echo "Exp 4: "`isDateInvalid '28-02-2014'`
echo "Exp 5: "`isDateInvalid '12_02_2002'`
echo "Exp 6: "`isDateInvalid '12.10.2099'`
echo "Exp 7: "`isDateInvalid '31/11/2000'`
Upvotes: 2
Reputation: 19
Blockquote
DATE = "$*"
[[ "${DATE}" != @(((([123][0]|[012][1-9])|3[1])?([ \/._-])(0[13578]|1[02])?([ \/._-])(19|20)[0-9][0-9])|(([123][0]|[012][1-9])?([ \/._-])\
(0[469]|11)?([ \/._-])(19|20)[0-9][0-9])|(([12][0]|[01][1-9]|2[1-8])?([ \/._-])02?([ \/._-])(19|20)[0-9][0-9])|(29?([ \/._-])02?([ \/._-])\
(19|20(0[48]|[2468][048]|[13579][26])))) ]] && echo error || echo good)
Upvotes: -2
Reputation: 4963
Here's a function to do some data validation this:
# Script expecting a Date parameter in MM-DD-YYYY format as input
verifyInputDate(){
echo ${date} | grep '^[0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9]$'
if [ $? -eq 0 ]; then
echo "Date is valid"
else
echo "Date is not valid"
fi
}
Upvotes: 1
Reputation: 2853
How about using awk
:
echo "31/12/1999" | awk -F '/' '{ print ($1 <= 31 && $2 <= 12 && match($3, /^[1-9][1-9][1-9][1-9]$/)) ? "good" : "bad" }'
It prints "good" if its valid date else prints "bad"
Upvotes: 2
Reputation: 75458
Simplest way for dd/mm/yyyy
exactly in Bash is:
if [[ $1 == [0-3][0-9]/[0-1][0-9]/[0-9][0-9][0-9][0-9] ]]
Or
if [[ $1 =~ ^[0-3][0-9]/[0-1][0-9]/[0-9]{4}$ ]]
Upvotes: 3
Reputation: 13016
First, check the form of the input using the regex. Then use awk to switch to mm/dd/yyyy and use date to validate. You can use the following expression in your if
statement:
echo "$1" | egrep -q '^[0-3][0-9]/[0-1][0-9]/[0-9]{4}$' && date -d "$(echo "$1" | awk 'BEGIN{FS=OFS="/"}{print $2"/"$1"/"$3}')" >/dev/null 2>&1
Upvotes: 5