Pular para o conteúdo

De vez em quando necessitamos fazer cálculos com datas para nós mesmos ou dentro de scripts. O comando date possui ótimos recursos para nos auxiliar nisso. Este post irá mostrar algumas das possibilidades de cálculo utilizando o date. Mas, antes de tudo, falarei um pouco sobre formatação.

Formatação de datas e hora

O comando date permite a formatação de datas e hora. Basta utilizar uma expressão de formatação iniciada com o caractere “soma”. Exemplos:

$ date
Ter Fev 14 16:15:48 BRST 2012

$ date "+%d de %B de %Y"
14 de fevereiro de 2012

No caso acima, %d refere-se ao dia, %b ao mês e %Y ao ano. Para saber mais sobre os parâmetros possíveis, consulte o manual on-line do comando date ($ man date) e procure por FORMAT.

Observação: BRST significa Brazilian Summer Time. Fora da época de horário de verão teremos BRT (Brazilian Time).

Cálculos elementares

Agora veremos alguns exemplos de cálculos com datas. Será necessário utilizar a chave -d. Apenas ressalto que o resultado final pode utilizar formatação, como descrito antes.

Datas e horas passadas e futuras

Alguns exemplos:

$ date
Ter Fev 14 16:35:46 BRST 2012

$ date -d "+10 days"
Sex Fev 24 16:38:00 BRST 2012

$ date -d "-10 days"
Sáb Fev  4 16:38:17 BRST 2012

$ date -d "+10 min"
Ter Fev 14 16:49:09 BRST 2012

$ date -d "-10 min"
Ter Fev 14 16:29:27 BRST 2012

$ date -d "+10 days -2 hours +10 min -50 secs"
Sex Fev 24 14:49:51 BRST 2012

Agora com formatação:

$ date -d "+10 days -2 hours +10 min -50 secs" '+%d %b %y, %H:%Mh'
24 Fev 12, 14:50h

$ date -d "+2 years +1 month -1 week" '+%d %b %y, %H:%Mh'
07 Mar 14, 15:47h

Exemplo em script:

#!/bin/bash
DATA=$(LANG=C date -d "-1 day" '+%b %e')
cat /var/log/syslog | grep "$DATA" | grep login

Na verdade, você tem que ser intuitivo para lidar com o date. Olha que exemplo louco:

$ date -d "next fri"
Sex Fev 17 00:00:00 BRST 2012

Ele mostrou a data da próxima sexta-feira (fri de friday). Outra saída, caso você não seja intuitivo, é ler o código fonte do comando. O manual on-line não cita as possibilidades. Então, tais possibilidades são (algumas aceitam plural, como hours): ago, day, fortnight, hour, last, min, month, next, now, sec, this, today, tomorrow, week, year e yesterday.

Outro exemplo:

$ date -d "last fri"
Sex Fev 10 00:00:00 BRST 2012

Agora preste atenção: day, fortnight, hour, min, month, sec, week e year são conhecidos como unidades e PODEM ser combinados com ago, last, next, now, this, today, tomorrow e yesterday, que são os modificadores. Exemplo:

$ date -d "last-week +1 day"
Qua Fev  8 17:55:00 BRST 2012

Unix Epoch

Para quem não sabe, o Unix Epoch é uma data de referência do Unix, ou seja, 01 de janeiro de 1970, às 00:00h. Os Unix utilizam bastante essa data. Por exemplo: quando você inclui um usuário no sistema com o comando adduser, uma linha é gerada no arquivo /etc/shadow. O terceiro campo dessa linha é a quantidade de dias decorridos desde o Unix Epoch. Então, é possível saber quando o usuário foi cadastrado ou quando a sua conta foi alterada pela última vez. Veja:

eriberto:$6$8wFWksz9$cGv03Q0y9B3bKVvao168QueUhv7ViMkS3SdXGOYOyqDaaUmjIit3m/0F6/98jTaglalgfatWGpVL4mp/x7oag/:15134:0:99999:7:::

No caso, 15134 é o número de dias desde o Epoch.

É importante dizer que a unidade do Epoch pode variar de aplicação para aplicação. Alguns logs, por exemplo utilizam a quantidade de segundos e não o de dias. É o caso do log do Squid. Veja o exemplo de uma linha desse log:

1294013828.588      0 84.63.123.123 TCP_MEM_HIT/200 943 GET http://www.debianet.com.br NONE/- text/css

No caso, 1294013828 é a quantidade de segundos. O 588 representa fração de segundos.

Cálculos com Epoch

Para saber o Epoch em segundos da data atual, utilize o comando:

$ date +%s
1329246450

Note que %s, segundo o manual on-line do comando date, significa a quantidade segundos passados desde a 00h de 01/01/1970. Para fazer o cálculo inverso, utilize a opção -d com o caractere “@” antes do número. Exemplo:

$ date -d @1329246450
Ter Fev 14 17:07:30 BRST 2012

Para saber o Epoch de uma data qualquer, com a hora, basta especificá-las. O detalhe é que tem que ser em inglês. Exemplo:

$ date +"%s" -d "Feb 14 17:07:30 BRST 2012"
1329246450

Também é possível remover a hora:

$ date +"%s" -d "Feb 14 2012"
1329184800

Assim, fazer cálculos com datas e Epoch ficou fácil. Basta utilizar os conceitos anteriores. Darei alguns exemplos. Comecemos calculando qual data representa o Epoch 15134 em dias.

$ date -d "1970-01-01 +15134 days"
Qui Jun  9 00:00:00 BRT 2011

Agora, veremos o que representa o Epoch 1329246450 em segundos. Já vimos uma forma fácil de fazer isso. Mas uma outra forma seria:

$ date -d "1970-01-01 +1329246450 secs"
Ter Fev 14 20:07:30 BRST 2012

Note que houve uma diferença de 3 horas entre a resposta anterior e esta, considerando ainda o horário de verão (estamos vivendo ele hoje). Isso me parece ser um bug do comando (ou de libraries). Mas se pedirmos o resultado em UTC (hora de Greenwitch), com a opção -u, o resultado será igual. Veja:

$ date -d @1329246450 -u
Ter Fev 14 19:07:30 UTC 2012

$ date -d "1970-01-01 +1329246450 secs" -u
Ter Fev 14 19:07:30 UTC 2012

Como no horário de verão estamos a menos de 2 horas de Greenwitch, o resultado correto brasileiro deveria ser 17:07h. Então, o cálculo com o comando “date -d @1329246450” foi mais preciso. Mas, digamos que o outro comando quebra o galho.

Comando cal

Já que estamos falando de datas, o comando cal também pode ser útil. Ele nos fornece um calendário on-line sempre que precisamos. Exemplos:

$ cal
   Fevereiro 2012
Do Se Te Qu Qu Se Sá
          1  2  3  4
 5  6  7  8  9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29

Há outras opções interessantes:

$ cal -3 —> fornece o calendário do mês anterior, do atual e do próximo.

$ cal 2012 —> mostra o calendário de 2012.

$ cal 9 1971 —> mostra o calendário de setembro de 1971.

$ cal -j —> mostra o calendário juliano.

Este post é particularmente útil para administradores de sistemas.

[]s!

5 comentários em “Cálculo de datas com o comando date no GNU/Linux”

  1. Gostei muito, mais ainda da parte que vc sugere ler o código. Estive com um problema que me chamou atenção sobre isto.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

dezessete − 12 =