Я пишу bash shell script в Linux, эта программа будет принимать дату (mm-dd-yyyy) в качестве параметра. Мне интересно, есть ли простой способ проверить, действительна ли дата? есть ли оператор, и я могу просто использовать тест для проверки?
Проверьте, является ли аргумент допустимой датой в оболочке bash
Ответ 1
Вы можете проверить с date -d "datestring"
Таким образом, date -d "12/31/2012"
действительна, но использование дефисов, например, date -d "12-31-2012"
, недействительно для date
.
Вы также можете использовать слова: date -d 'yesterday'
или date -d '1 week ago'
действительны.
Ответ 2
Вы можете извлечь значения дня, месяца и года из значения даты ввода ММ-ДД-ГГГГ и подтвердить его как однозначный (ISO) формат YYYY-MM-DD (вы можете проверить DD-MM-YYY отформатированной даты как "правильной" с использованием даты, например 25-12-2010, но это не действительная дата MM-DD-YYY, поэтому необходимо сначала изменить формат даты)
Действительная дата в правильном формате в порядке
30 ноября 2005 года действителен:
$ 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
Недействительная дата в правильном формате НЕ ОК
31 ноября 2005 года не подтверждается:
$ 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
Действительная дата в неправильном формате НЕ ОК
20 апреля 1979 года в формате 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
Альтернативный более простой метод: используйте переменную string 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
Ответ 3
Для использования script я сохранил это как можно проще. Проверка значения даты с помощью функции даты, а затем проверка кода выхода процесса.
date -d "02/01/2000" 2>: 1>:; echo $?
Это приведет к перенаправлению стандартной и стандартной ошибки в null :
и использование эха для возврата кода выхода с помощью $?
позволяет мне проверять на 0 = хорошую дату и 1 = плохую дату.
Ответ 4
Для меня работали хорошо. Большое спасибо моему коллеге Тайлеру Чемберлену за решение 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."
Я тестировал этот script в системе на основе Red Hat, на базе Debian и OSX, и работал на всех трех платформах. У меня не было времени на тестирование в Windows (Cygwin).
Ответ 5
Операторы caseупрощают поддержку нескольких форматов и захват деталей даты, т.е.
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
Надеюсь, это поможет.
Ответ 6
Вы можете использовать функцию strptime()
, доступную в Python time или datetime или модуль Perl Time:: Piece.
Ответ 7
Для проверки дат ГГГГ-ММ-ДД (ISO 8601) на OSX в оболочке BASH, следующий подход проверяет как формат, так и дату.
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 "$?"
}
- Сначала он использует совпадение с регулярным выражением для проверки формата.
- Затем он преобразует дату в время эпохи, а затем обратно в дату.
- Если исходные и дважды преобразованные даты совпадают, то это действительно.
Проверьте действительную дату: 2005-11-30
$ isYYYYMMDDdate 2005-11-30
0
Проверьте неверную дату: 2005-11-31
$ isYYYYMMDDdate 2005-11-31
1
Проверьте правильность неверной даты: 1979-20-04
$ isYYYYMMDDdate 1979-20-04
1