Ferramenta no UNIX para subtrair datas

22

Existe alguma ferramenta no Solaris UNIX (portanto, nenhuma ferramenta GNU disponível) para subtrair datas? Eu sei que no Linux temos gawk que pode subtrair uma data da outra. Mas, no Solaris, o máximo que temos é nawk (melhorou awk ), que não pode executar cálculos de data. Também não posso usar perl.

Existe alguma maneira de fazer cálculos de data como 20100909 - 20001010 ?

UPDATE: é bc capaz de realizar cálculos de datas?

    
por jyz 09.09.2010 / 21:31

11 respostas

10

Aqui está um script awk que acabei de escrever, deve funcionar com um awk POSIX. Você terá que experimentar a versão do Solaris; lembre-se que existem duas versões do Awk no Solaris também, uma em / bin e uma em / usr / xpg4 / bin / awk (que é nawk, acredito).

BEGIN {
    daysofmonth["01"] = 0; daysofmonth["02"] = 31; daysofmonth["03"] = 59;
    daysofmonth["04"] = 90; daysofmonth["05"] = 120; daysofmonth["06"] = 151;
    daysofmonth["07"] = 181; daysofmonth["08"] = 212; daysofmonth["09"] = 243;
    daysofmonth["10"] = 273; daysofmonth["11"] = 304; daysofmonth["12"] = 334;
    fullday = 86400;
}
/[12][09][0-9][0-9][01][0-9][0123][0-9]/ {
    year = substr($0, 1, 4); month = substr($0, 5, 2); day = substr($0, 7, 2);
    date = ((year - 1970) * 365.25) + daysofmonth[month] + day - 1;
    if ((year % 4) == 0 && month > 2) { date = date + 1; }
    print date * fullday - (25200);
}
{}

Transmita uma string de data YYYYmmdd e ela será convertida em número de segundos desde a Epoch (com um pouco de limite por estar nos limites do dia). Então você será capaz de subtrair os dois.

today='echo 20110210 | awk -f convdate.awk'
then='echo 20001231 | awk -f convdate.awk'
sincethen='expr $today - $then'
    
por 11.02.2011 / 02:01
13

Infelizmente, nenhum dos utilitários de linha de comando POSIX fornece aritmética em datas. date -d e date +%s são o caminho a percorrer se você os tiver, mas são extensões GNU.

Há um hack desajeitado com touch que funciona para verificar se uma data é pelo menos n dias no passado:

touch -t 201009090000 stamp
if [ -n "$(find stamp -mtime +42)" ]; then ...

(Observe que esse código pode estar desativado em um se o DST for iniciado ou interrompido no intervalo e o script for executado antes da 1h).

Várias pessoas acabaram implementando bibliotecas de manipulação de datas no shell Bourne ou POSIX. Existem alguns exemplos e links na FAQ do comp.unix.shell .

Instalar ferramentas GNU pode ser o caminho menos doloroso.

    
por 09.09.2010 / 23:10
11

Eu tentaria usar o comando date , que é parte do POSIX, então é praticamente todo lugar. UPDATE: Infelizmente, parece que -d não faz parte da data do POSIX e provavelmente não existe no Solaris. Assim, é provável que isso não responda à pergunta dos OPs.

d1='date -d 20100909 +%s'
d2='date -d 20001010 +%s'

Agora, d1 e d2 são inteiros que correspondem a segundos desde a época do unix. Assim, para obter a diferença entre os dois, subtraímos ( $((d1-d2)) no bash) e convertemos para qualquer unidade que quisermos. Os dias são mais fáceis:

echo "$(((d1-d2)/86400)) days"

Como fazer a conversão provavelmente será diferente se você não tiver bash. A maneira mais portátil pode ser usar expr ( página man posix do expr ).

    
por 09.09.2010 / 21:49
8

Para o registro, dateutils é minha tentativa de fornecer um conjunto de ferramentas portáteis que cobrem aritmética de data. Seu exemplo se resume a

ddiff -i '%Y%m%d' 20001010 20100909
=>
  3621

O -i especifica o formato de entrada.

    
por 11.04.2012 / 08:29
4

É provável que o Perl seja instalado, e é fácil pegar módulos do CPAN , instalá-los em seu diretório pessoal e < href="http://perldoc.perl.org/lib.html"> referem-se a eles em seu programa. Nesse caso, o módulo Date :: Calc tem Delta_Days sub-rotina que ajudará.

    
por 10.02.2011 / 20:49
3

Data do GNU no Solaris:

Eu digo isso de novo:

Muitos Solaris SysAdmins se orgulham de não instalar deliberadamente os pacotes oficiais da Sun (agora Oracle) que tornam o sistema Solaris "compatível com GNU" quando configuram um novo host. Me bate porque.

O GNU Date é excelente e deve estar disponível por padrão em qualquer host do Solaris, IMHO.

No Solaris 10

Instale o pacote SFWcoreu a partir do CD do Solaris Companion. Após a instalação, você encontrará a data do GNU em /opt/sfw/bin/date

No Solaris 11

Você pode já tê-lo como eu acredito que faz parte da instalação padrão. No entanto, ele é chamado de gdate para diferenciá-lo da versão de data da Sun.

Faça isso se não estiver instalado:

pkg install //solaris/file/gnu-coreutils
    
por 15.08.2012 / 17:40
2

Se você tem Python:

from time import *
date1 = strptime("20100909","%Y%m%d")
date2 = strptime("20001010","%Y%m%d")
diff = mktime(date1) - mktime(date2)
print repr(d/86400) + " days"

Você marcou sua pergunta "gawk", mas não há "ferramentas do GNU". Gawk tem aritmética de data.

    
por 09.09.2010 / 23:54
2

python:

 from datetime import datetime as dt
 a = dt(2010, 9, 9)
 b = dt(2000, 10, 10)
 print (a - b).days
    
por 11.02.2011 / 07:27
1

1. Defina date1 e date2 em %j dia do formato do ano (001..366)

user@linux:~$ date1='date -d 20100909 +%j' 
user@linux:~$ date2='date -d 20001010 +%j'

2. Calcule a diferença com expr

user@linux:~$ datediff='expr $date2 - $date1'

3. Então, a resposta é 32 dias

user@linux:~$ echo $datediff days
32 days
user@linux:~$ 

... ou solução de uma linha

user@linux:~$ echo $(( $(date -d 20001010 +%j) - $(date -d 20100909 +%j) )) days
32 days
user@linux:~$ 

ou

user@linux:~$ expr $(date -d 20001010 +%j) - $(date -d 20100909 +%j)
32
user@linux:~$

ou

user@linux:~$ expr 'date -d 20001010 +%j' - 'date -d 20100909 +%j'
32
user@linux:~$ 
    
por 22.06.2018 / 14:13
0

Com data BSD para macOS:

echo "Quelle est la date de début ?"
read DATE_DE_DEBUT
echo "Quelle est la date de fin ?"
read DATE_DE_FIN
ANNEE=$(($(echo $DATE_DE_FIN | awk -F "/" '{print $3}')-$(echo $DATE_DE_DEBUT  | awk -F "/" '{print $3}')))

echo " "

if [[ $ANNEE > 0 ]]; then

for((annee=$ANNEE-1 ; $ANNEE ; annee++))

  do
  #echo $annee  
  for((mois=0 ; 13 - $mois ; mois++))
      do
  #   echo année:$annee mois:$mois
          for((jour=0 ; 32 - $jour ; jour++))
              do
 #             echo année:$annee mois:$mois jour:$jour
           TEST=$(date -Rjf"%d/%m/%Y" -v +"$annee"y -v +"$mois"m -v +"$jour"d $DATE_DE_DEBUT +"%d/%m/%Y")
           if [[ $TEST = $DATE_DE_FIN ]]; then
                  echo "Différence entre le $DATE_DE_DEBUT et le $DATE_DE_FIN";
                  echo "est de :";
                  echo "$annee année(s) $mois mois $jour jour(s)";
             exit 0;
            fi


          done 
  done
  done

 else 
 annee=0
 for((mois=0 ; 13 - $mois ; mois++))
      do
#      echo année:$annee mois:$mois
          for((jour=0 ; 32 - $jour ; jour++))
              do
              #echo année:$annee mois:$mois jour:$jour
              TEST=$(date -Rjf"%d/%m/%Y" -v +"$annee"y -v +"$mois"m -v +"$jour"d $DATE_DE_DEBUT +"%d/%m/%Y")
              if [[ $TEST = $DATE_DE_FIN ]]; then 
                      echo "Différence entre le $DATE_DE_DEBUT et le $DATE_DE_FIN";
                     echo "est de :";
                     echo "$annee année(s) $mois mois $jour jour(s)";
              exit 0;
              fi
              done
      done

fi
    
por 08.04.2017 / 20:07
0

Você pode usar a biblioteca Velour do awk para retornar a diferença em segundos:

$ velour -n 'print t_utc(2010, 9, 9) - t_utc(2000, 10, 10)'
312854400

Ou dias:

$ velour -n 'print t_secday(t_utc(2010, 9, 9) - t_utc(2000, 10, 10))'
3621
    
por 29.12.2016 / 04:43