Validação de data no shell

14

Desejo validar o formato da data abaixo no shell script

2015-Jul-13

Estou usando, date -d "2015-Jul-13" +"%Y-%b-%d"mas está dando erro como

date: invalid date '2015-Jul-13'
chhaya vishwakarma
fonte
@ Pandand: OP é claro sobre sua pergunta. O OP deseja validar (verifique se a data digitada é válida ou não) o formato de data mencionado, mas está dizendo que a data digitada é inválida.
Thushi 13/07/2015
O GNU datenão reconhece YYYY-MMM-DD. Você poderia usar YYYY-MM-DDou DD MMM YYYYpreferir?
roaima 13/07/2015
Tenho certeza que atsim, e - eu acho - touchtambém. Eu escrevi um funvtion data shell de validação com base em touchuma vez ... Não, não touch- ele só lida com números, mas atfaz alguma análise bastante profunda ...
mikeserv
O comentário de deixar @Thushi clara redundante por nós
Pandya
6
Descaracterizou o título: validação de Data é o inferno
Adam Davis

Respostas:

12

O GNU datenão suporta YYYY-MMM-DD. No entanto, ele entende DD-MMM-YYYY. Portanto, se você realmente precisa lidar com datas desse formato, pode fazê-lo com algo assim, que simplesmente troca os argumentos para um formato que dateespera:

ymd='2015-Jul-13'

dmy=$(echo "$ymd" | awk -F- '{ OFS=FS; print $3,$2,$1 }')
if date --date "$dmy" >/dev/null 2>&1
then
    echo OK
fi

Aqui está uma solução totalmente shell. Por fim, as IFS=-instruções dizem ao shell para dividir uma próxima linha de comando por hífen, em -vez de espaço em branco. Ele set $ymdanalisa a $ymdvariável como em uma linha de comando, mas agora é dividida por hífen, atribuindo valores aos parâmetros $1, $2 e seq . O echo "$3-$2-$1"trivialmente gera os três valores capturados em ordem inversa.

ymd='2015-Jul-13'

dmy=$(IFS=-; set $ymd; echo "$3-$2-$1")
if date --date "$dmy" >/dev/null 2>&1
then
    echo OK
fi
roaima
fonte
@mikeserv: Coolness! Funcionou com: ymd=$(IFS=-;set $ymd; echo "$3-$2-$1") você poderia revelar a mágica por trás do setcomando?
21815 joepd
11

Da página de manual: -

DATE STRING
       The --date=STRING is a mostly free format human readable date string such as "Sun, 29 Feb 2004 16:21:42 -0800"
       or  "2004-02-29  16:21:42" or even "next Thursday".  A date string may contain items indicating calendar date,
       time of day, time zone, day of week, relative time, relative date, and numbers.  An empty string indicates the
       beginning  of  the  day.   The  date string format is more complex than is easily documented here but is fully
       described in the info documentation.

Mas parece não reconhecer o YYYY-MMM-DDformato. Então, você pode usar abaixo ou similar, como:

$ date -d "2015-07-13" +"%Y-%b-%d"
2015-Jul-13
$ date -d "Jul 13 2015" +"%Y-%b-%d"
2015-Jul-13
$ date -d "13 Jul 2015" +"%Y-%b-%d"
2015-Jul-13

OU você deve convertê - lo / formatá- lo antes de enviá - lo para date!

Consulte também Como você especifica um formato para a entrada até a data?


Eu recomendo visitar: formatos de entrada de data .

Aqui estão as regras.

Para meses numéricos , o formato ISO 8601 'ano-mês-dia' é permitido, onde ano é qualquer número positivo, mês é um número entre 01 e 12 e dia é um número entre 01 e 31. Um zero à esquerda deve estar presente se um número for menor que dez. Se o ano for 68 ou menor, 2000 será adicionado a ele; caso contrário, se o ano for menor que 100, 1900 será adicionado a ele. O construto 'mês / dia / ano', popular nos Estados Unidos, é aceito. Também 'mês / dia', omitindo o ano.

Os meses literais podem ser escritos na íntegra: 'Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', ' Novembro "ou" Dezembro ". Os meses literais podem ser abreviados para as três primeiras letras, possivelmente seguidos de um ponto abreviado. Também é permitido escrever 'Sept' em vez de 'September'.

Quando os meses são escritos literalmente , a data do calendário pode ser dada como uma das seguintes opções:

 dia mês ano
 dia mês
 mês dia dia ano
 dia-mês-ano

enfatizado por mim

Aqui você pode ver que não há formato como ano-mês-dia ! (por meses são escritos literalmente)

Pandya
fonte
7

Com zshvocê poderia usar o strftimebuiltin (disponível via zsh/datetime) com -r(reverso):

timesting no formato strftime -r

que usa o formato para analisar a timesting e gerar o número de segundos desde a época:

zmodload zsh/datetime
strftime -r %Y-%b-%d 2015-Jul-13
1436734800

Isso ocorre se a data for inválida:

strftime -r %Y-%b-%d 2015-Jul-33
zsh: strftime: 5: formato não correspondido

Você também pode converter os segundos desde a época para qualquer outro formato de data padrão / personalizado, por exemplo

strftime '%A, %B %d, %Y' 1447970400
Sexta-feira, 20 de novembro de 2015
don_crissti
fonte