如何在Unix
中验证日期。
日期格式为DD-MM-YYYY
的日期
例如,如果我运行一个脚本./ValidateDate.sh DD-MM-YYYY
,那么它应该检查日期是否采用这种格式,并且日期是否存在。
如果日期有效且格式如上,则继续执行下一条其他打印消息'无效日期'
感谢。
答案 0 :(得分:3)
您创建的任何shell脚本可能无法在所有各种版本的Unix / Linux上运行。
BSD date命令(在OS X和Solaris上找到)在接收日期和验证格式方面做得很好。它要求您指定日期格式,但一旦这样做,它就没有问题:
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和其他使用GNU日期的系统也可以验证日期,但使用不同的语法:
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
我说带点运气因为它可以通过date
命令来确定您的约会格式。这通常有效,并且可以使用YYYY-MM-DD
格式,但这可能令人困惑:
想象一下:
$ DATE="15/6/2014" # It's June 15, 2014
$ date -d "$DATE"
date: invalid date `15/6/2014' # Invalid?
这是因为在我的时区,dd/mm/yyyy
格式不是有效格式。在我的时区,日期应为mm/dd/yyyy
。为了解决这个问题,您可以使用Wintermute's建议,并在使用GNU的日期格式之前将日期格式化为ISO格式。
更多通用的可能性是使用Perl或Python来判断日期是否正确:
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
如果$DATE
不是%Y-%m-%d
格式的有效日期,则此Perl oneliner将返回非零错误状态。
答案 1 :(得分:0)
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"
它将字符串转换为纪元,然后将纪元转换回原文。
编辑:
以为我会在测试这个作品后添加日期
来自01-01-0
致31-12-2147483647
虽然缺点是在你低于1000年后,你必须从年份中删除前导零。
答案 2 :(得分:0)
您可以使用date
实用程序验证日期,但首先必须将输入转换为可以理解的内容。我建议ISO表示(总是)。例如,它可能看起来像这样:
#!/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
答案 3 :(得分:0)
如果您愿意将验证分为两个步骤,则可以相当轻松地完成此操作。首先,检查字符串的格式是否正确:
date=$1
[[ $date =~ ([0-9][0-9])-([0-9][0-9])-([0-9]+) ]] || { printf "Invalid date format\n"; exit 1; }
如果该测试通过,您可以提取日,月和年字段,然后验证每个字段是否在正确的范围内。
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; }