检查参数是否是bash shell中的有效日期

时间:2012-05-25 17:53:42

标签: linux bash shell

我正在Linux中编写一个bash shell脚本,该程序将接受一个日期(mm-dd-yyyy)作为参数。我想知道是否有一种简单的方法来检查日期是否有效?是否有操作员,我可以使用测试来检查?

8 个答案:

答案 0 :(得分:14)

您可以查看date -d "datestring"

所以date -d "12/07/2012"有效,但使用连字符对bash无效。

您还可以使用字词:date -d 'yesterday'date -d '1 week ago'都有效。

答案 1 :(得分:10)

您可以从输入日期值MM-DD-YYYY中提取日,月和年值,并将其验证为明确的(ISO)格式YYYY-MM-DD(您可以验证DD-MM-YYY)使用日期格式化日期为“正确”,例如25-12-2010,但它不是有效的MM-DD-YYY日期,因此需要先更改日期格式)


格式正确的有效日期为OK

2005年11月30日有效:

$ DATE=11-30-2005; d=${DATE:3:2}; m=${DATE:0:2}; Y=${DATE:6:4}; echo "year=$Y, month=$m, day=$d"; if date -d "$Y-$m-$d" &> /dev/null; then echo VALID; else echo INVALID; fi
year=2005, month=11, day=30  
VALID

$ DATE=11-30-2005; if date -d "${DATE:6:4}-${DATE:0:2}-${DATE:3:2}" &> /dev/null; then echo VALID; else echo INVALID; fi
VALID

格式正确的无效日期不正常

2005年11月31日未确认:

$ DATE=11-31-2005; d=${DATE:3:2}; m=${DATE:0:2}; Y=${DATE:6:4}; echo "year=$Y, month=$m, day=$d"; if date -d "$Y-$m-$d" &> /dev/null; then echo VALID; else echo INVALID; fi
year=2005, month=11, day=31  
INVALID

$ DATE=11-31-2005; if date -d "${DATE:6:4}-${DATE:0:2}-${DATE:3:2}" &> /dev/null; then echo VALID; else echo INVALID; fi
INVALID

格式错误的有效日期不正常

1979年4月20日,DD-MM-YYYY格式未作为MM-DD-YYYY日期验证:

$ DATE=20-04-1979; d=${DATE:3:2}; m=${DATE:0:2}; Y=${DATE:6:4}; echo "year=$Y, month=$m, day=$d"; if date -d "$Y-$m-$d" &> /dev/null; then echo VALID; else echo INVALID; fi
year=1979, month=20, day=04  
INVALID

$ DATE=20-04-1979; if date -d "${DATE:6:4}-${DATE:0:2}-${DATE:3:2}" &> /dev/null; then echo VALID; else echo INVALID; fi
INVALID

替代更简单的方法:使用BASH变量字符串替换连字符斜杠

$ DATE="04-30-2005"; [[ $(date -d "${DATE//-/\/}" 2> /dev/null) ]] && echo VALID || echo INVALID
VALID

$ DATE="04-31-2005"; [[ $(date -d "${DATE//-/\/}" 2> /dev/null) ]] && echo VALID || echo INVALID
INVALID

答案 2 :(得分:7)

对于脚本使用,我保持尽可能简单。使用日期函数测试日期值,然后检查进程的退出代码。

date -d "02/01/2000" 2>: 1>:; echo $?

这会将标准输入和标准错误重定向到空:并使用echo返回带有$?的退出代码,这样我就可以检查0 =良好日期和1 =错误日期。

答案 3 :(得分:4)

以下对我来说效果很好。非常感谢我的同事Tyler Chamberlain为OSX解决方案。

# Validate a given date/time in Bash on either Linux or Mac (OSX).

# Expected date/time format (in quotes from the command line):  YYYY-MM-DD HH:MM:SS
# Example(s):  ./this_script "2012-02-29 13:00:00"   # IS valid
#              ./this_script "2013-02-29 13:00:00"   # Is NOT valid

START_DATETIME=$1

function report_error_and_exit
{
   local MSG=$1
   echo "$MSG" >&2
   exit 1
}

# We can use OSTYPE to determine what OS we're running on.
# From http://stackoverflow.com/questions/394230/detect-the-os-from-a-bash-script

# Determine whether the given START_DATETIME is valid.
if [[ "$OSTYPE" == "linux-gnu" ]]
then
   # Validate the date on a Linux machine (Redhat or Debian).  On Linux, this is 
   # as easy as adding one minute and checking the return code.  If one minute 
   # cannot be added, then the starting value is not a valid date/time.
   date -d "$START_DATETIME UTC + 1 min" +"%F %T" &> /dev/null
   test $? -eq 0 || report_error_and_exit "'$START_DATETIME' is not a valid date/time value. $OSTYPE"
elif [[ "$OSTYPE" == "darwin"* ]]
then
   # Validate the date on a Mac (OSX).  This is done by adding and subtracting
   # one minute from the given date/time.  If the resulting date/time string is identical 
   # to the given date/time string, then the given date/time is valid.  If not, then the
   # given date/time is invalid.
   TEST_DATETIME=$(date -v+1M -v-1M -jf "%F %T" "$START_DATETIME" +"%F %T" 2> /dev/null)

   if [[ "$TEST_DATETIME" != "$START_DATETIME" ]]
   then
      report_error_and_exit "'$START_DATETIME' is not a valid date/time value. $OSTYPE"
   fi
fi

echo "The date/time is valid."

我在基于Red Hat的系统,基于Debian的系统和OSX上测试了这个脚本,并且它在所有三个平台上都按预期工作。我没有时间在Windows上测试(Cygwin)。

答案 4 :(得分:2)

案例陈述使得支持多种格式和捕获日期部分变得容易,即

 case ${date} in
    [0-3][0-9]-[0-1][0-9]-[0-9][0-9][0-9][0-9] )
       yr=...
       mn=...
       dy=... 
    ;;
    [0-1][0-9]-[0-3][0-9]-[0-9][0-9][0-9][0-9] )
       yr=...
       dy=... 
       mn=...
    ;;
    .... other formats
    ;;
    * )
      echo "ERROR on date format, from value=$date, expected formats ..."
      return 1
    ;;     
 esac

我希望这会有所帮助。

答案 5 :(得分:2)

date命令将解析由-d参数给定的日期。如果日期无效,则将错误消息打印到STDERR,并且date退出并显示错误状态。如果日期有效,它将在STDOUT上打印日期并以成功状态退出。

因此,date -d "$date"可以直接在bash if语句中使用。

第一个难题是,要防止打印有效日期的消息,您需要使用/dev/null将STDOUT重定向到>/dev/null

第二个折痕是date接受一个空字符串作为有效日期,而没有任何抱怨。在大多数情况下,这应该意味着您的用户没有输入应该输入的日期。您将要使用测试[ "z$date" != "z" ]

分别测试一个空日期

date也接受多种格式。如果您使用的是实际的bash(而不是dash或其他sh品种,则可以对首选格式使用正则表达式,而不是简单检查空字符串。例如,要检查我的首选ISO格式,可以使用:[[ "$date" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]

date=2001-01-01
if [ "z$date" != "z" ] && date -d "$date" >/dev/null
then
  echo "VALID DATE"
fi

如果您使用无效的日期(例如2001-01-53)尝试此操作,它将不会进入if并显示出来:

日期:无效日期“ 2001-01-53”

或者,您可以检查日期是否无效并退出:

date=2001-01-01
if [ "z$date" == "z" ]
then
  echo "No date specified"
  exit 1
fi
if ! [[ "$date" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]
then
  echo "Expected date in YYYY-MM-DD format"
  exit 1
fi
if ! date -d "$date" >/dev/null
then
  exit 1
fi
echo "VALID DATE"

答案 6 :(得分:1)

您可以使用Python的timedatetime模块或Perl的Time::Piece模块中提供的strptime()函数。

答案 7 :(得分:0)

要在BASH shell中的OSX上验证YYYY-MM-DD(ISO 8601)日期,以下方法将同时验证格式和日期。

isYYYYMMDDdate() {
  [[ "$1" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]] && [[ "$1" == $(date -r $(date -j -f "%Y-%m-%d" "$1" "+%s") '+%Y-%m-%d') ]] &> /dev/null; echo "$?"
}
  1. 它首先使用正则表达式匹配来检查格式。
  2. 然后,它将日期转换为纪元时间,然后再转换回日期。
  3. 如果原始日期和两次转换日期匹配,那么它是有效的。

测试有效日期:2005-11-30

$ isYYYYMMDDdate 2005-11-30
0

测试无效日期:2005-11-31

$ isYYYYMMDDdate 2005-11-31
1

测试格式错误的有效日期:1979-20-04

$ isYYYYMMDDdate 1979-20-04
1