verificar se o argumento date está no formato aaaa-mm-dd [closed]

3

Existe uma maneira de verificar se um argumento de data está no formato correto (AAAA-MM-DD)?

Eu peguei isso da web, mas não funciona para mim:

date "+%Y-%m-%d" -d "2015-10-11" > /dev/null  2>&1
echo $?

Espero um resultado 0 , mas esse não é o caso. Alguém pode dizer de outra maneira?

    
por louggle 15.10.2015 / 10:41

4 respostas

7

Isso verificará o formato correto (AAAA-MM-DD) em bash (com correspondência regex interna):

if [[ $1 =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]
  then echo "Date $1 is in valid format (YYYY-MM-DD)"
  else echo "Date $1 is in an invalid format (not YYYY-MM-DD)"
fi

Executar:

./script.sh 2015-12-10

Saída:

Date 2015-12-10 is in valid format (YYYY-MM-DD)

Ele não verifica se a data em si é válida, apenas o formato (como indicado na pergunta, "Verifique se um argumento de data está no formato correto (AAAA-MM-DD") )

Se você precisar verificar o formato de data e validar o valor da data, tente algo como:

if [[ $1 =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]] && date -d "$1" >/dev/null
      then echo "Date $1 is valid and matches the format (YYYY-MM-DD)"
fi

Isso descartará datas inválidas como 0000-88-77 que passam a correspondência de expressão regular.

(O crédito vai para @glenn jackman por esta sugestão.)

    
por 15.10.2015 / 11:50
0

Você precisa aprender a escrever uma expressão regular para validar que uma data está no formato correto. aaaa-mm-dd

Um método fácil seria fazer isso em uma linha para que você possa brincar com a data e a expressão regular e aprender rapidamente.

Eu usaria echo para produzir a data e, em seguida, egrep para aplicar a expressão regular e indicar se ela encontrou uma correspondência ou não. Olhe para a página de manual para egrep , você verá que há uma opção -c que imprime uma contagem de correspondências, desde que você enviaria apenas uma data, a contagem seria 0 ou 1, dependendo de se encontrou uma jogo.

Aqui está o seu um forro para brincar.

echo 0000-00-00 |egrep -c -e 'regular-expression-in-here'

insira expressões regulares (você pode começar com o AP que deu a resposta) para ver como funciona. Altere a data e veja o que ela valida. Aqui está outro, um pouco diferente.

[0-9]{4}-[0-1][0-9]-[0-3][0-9]

    
por 15.10.2015 / 12:16
0

Você pode simplesmente comparar se a saída date da sua data corresponde ao valor original:

d="2015-10-11"
if [ "'date '+%Y-%m-%d' -d $d 2>/dev/null'" = "$d" ]
then
  echo $d is a valid YYYY-MM-DD date
else
  echo $d is NOT a valid YYYY-MM-DD date
fi
    
por 15.10.2015 / 13:50
0

Você não marcou um sistema operacional e, como está usando ksh , provavelmente não está usando o Linux e pode estar usando o Solaris. O comando date que você der funcionará, mas é para o GNU date onde -d (ou --date ) é um aprimoramento do GNU.

Então a opção simples é usar GNU date , você pode precisar instalar o pacote GNU coreutils, ou você pode já tê-lo (verifique em /usr/sfw/bin no Solaris) ele pode estar disponível possivelmente como gdate ou gnudate . Isso valida corretamente a data no formato AAAA-MM-DD (ao contrário dos exemplos de expressão regular em outro lugar que aceitarão 2015-31-01)

Em vez disso, você pode usar o comando touch em um similar e mais portátil (POSIX) caminho

touch -c -d 2015-12-12T00:00:00 /tmp/does-not-exist
  • use -c para que um arquivo não seja criado
  • anexe T00: 00: 00 à data para criar um carimbo de hora válido

(No entanto, se você estiver usando o Solaris, algumas versões não têm -d , mas algumas versões têm pelo menos um bug / falta de funcionalidade onde elas não são validadas e tentam ser inteligentes, então "2015-02 -29 "torna-se" 2015-03-01 "sem erros, pelo que não pode utilizar estas versões para validação de datas.)

Eu prefiro assim, é robusto e portátil supondo que você tenha gawk (ou mawk , mas tradicional nawk não possui essas funções de tempo).

#!/usr/local/bin/gawk -f
BEGIN{
    split(ARGV[1],bb,/-/)
    tm=mktime( bb[1] " " bb[2] " " bb[3] " 00 00 00")
    tms=sprintf("%04i-%02i-%02i",bb[1],bb[2],bb[3])
    if (tms==strftime("%Y-%m-%d",tm)) exit 0
    exit 1
}

O acima

  • pega o primeiro argumento e divide o caractere "-".
  • mktime() para determinar um registro de data e hora da época para o AAAA-MM-DD indicado
  • sprintf() para normalizar o AAAA-MM-DD (primeiro 0)
  • strftime() para converter o tempo de época de volta para AAAA-MM-DD e comparar como uma cadeia de caracteres

A razão para o acréscimo de converter e converter é pegar o caso em que datas questionáveis são reinterpretadas pela biblioteca C mktime() , como é o caso do glibc no linux (o mesmo problema que com o Solaris touch acima).

Cuidar do formato correto de AAAA-MM-DD pode ou não significar preocupação com a validade da data (algo que date fará) e pode até significar ser capaz de eliminar Datas do formato AAAA-DD-MM . Se você deseja apenas confirmar que o formato é "date like", uma expressão regular será suficiente:

grep -qE "^[0-9]{4}-[01]?[0-9]-[0123]?[0-9]$"
grep -qE "^[12][0-9]{3}-(0?[1-9]|10|11|12)-(0?[1-9]|[12][0-9]|3[01])$"

(No Solaris, use /usr/xpg4/bin/grep , não o padrão grep ) O primeiro rejeitará a maioria das datas falsas, o segundo rejeitará quase todas as datas falsas. Com -q não haverá saída e você poderá usar o código de retorno conforme o esperado. Tome cuidado para ancorar ( ^...$ ) ou, de outra forma, restringir a expressão regular para que ela não corresponda simplesmente à substring válida, por exemplo, 2015-12-12345

    
por 15.10.2015 / 14:00