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