bash 在unix中验证DD-MM-YYYY格式的日期

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27380025/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 11:58:42  来源:igfitidea点击:

validate date in unix for DD-MM-YYYY format

bashunixarguments

提问by Rubab

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-YYYYthen 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'

如何验证Unix.
日期格式在哪里DD-MM-YYYY
例如,如果我运行一个脚本,./ValidateDate.sh DD-MM-YYYY那么它应该检查日期是否采用这种格式以及日期是否存在。
如果日期有效且采用上述格式,则继续下一个其他打印消息“无效日期”

Thanks.

谢谢。

回答by David W.

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.

您创建的任何 shell 脚本可能无法在所有不同的 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:

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 and other systems that use GNU's date can also validate the date, but use a different syntax:

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

I say With a bit of luckbecause it's up to the datecommand to figure out your date's format. This normally works, and will work with your YYYY-MM-DDformat, but it can be confusing:

我说有点运气,因为这取决于date确定日期格式的命令。这通常有效,并且适用于您的YYYY-MM-DD格式,但可能会令人困惑:

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/yyyyformat isn't a valid format. In my timezone, the date should be mm/dd/yyyy. To get around this you can use Wintermute'ssuggestion and format the date into ISO format before using GNU's date format.

那是因为在我的时区,dd/mm/yyyy格式不是有效格式。在我的时区,日期应该是mm/dd/yyyy. 为了解决这个问题,您可以使用Wintermute 的建议并将日期格式化为 ISO 格式,然后再使用 GNU 的日期格式。

A more universalpossibility is to use Perl or Python to figure out if the date is correct:

普遍的可能性是使用 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

This Perl oneliner will return a non-zero error status if $DATEisn't a valid date in %Y-%m-%dformat.

如果格式$DATE不是有效日期,则此 Perl oneliner 将返回非零错误状态%Y-%m-%d

回答by David W.

awk way

awk 方式

awk 'split(
 #!/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 "" | sed -n "/$PATTERN/ { s/$PATTERN/--/; p }") > /dev/null 2>&1 ; then
     echo valid
 else
     echo invalid
 fi
,a,"-"){print strftime("%d-%m-%Y",mktime(a[3]" "a[2]" "a[1]" 00 00 00"))==
date=
[[ $date =~ ([0-9][0-9])-([0-9][0-9])-([0-9]+) ]] || { printf "Invalid date format\n"; exit 1; }
?"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

以为我会在测试此日期后添加
01-01-0
31-12-2147483647

Although a drawback is after you go below the year 1000 you have to remove leading zeros from the year.

尽管缺点是在低于 1000 年之后,您必须从年份中删除前导零。

回答by Wintermute

You can validate the date with the dateutility, 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:

您可以使用该date实用程序验证日期,但首先必须将输入转换为它可以理解的内容。我建议 ISO 代表(总是)。例如,它可能如下所示:

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; }

回答by chepner

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:

如果您愿意将验证分为两个步骤,您可以很容易地做到这一点。首先,检查字符串的格式是否正确:

##代码##

If that test passes, you can extract the day, month, and year fields, then verify that each falls in the correct range.

如果该测试通过,您可以提取日、月和年字段,然后验证每个字段是否都在正确的范围内。

##代码##