web-development-kb-pt.site

Ferramenta no UNIX para subtrair datas

Existe alguma ferramenta no Solaris UNIX (portanto, nenhuma GNU disponível) para subtrair datas? Eu sei que no Linux temos gawk que pode subtrair uma data da outra. Solaris, o máximo que temos é nawk (aprimorado 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 datas como 20100909 - 20001010?

ATUALIZAÇÃO: bc é capaz de executar cálculos de datas?

23
jyz

Aqui está um script awk que acabei de escrever, deve funcionar com um awix POSIX. Você terá que experimentar a versão Solaris; lembre-se de que também existem duas versões do Awk no Solaris, uma em/bin e outra 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);
}
{}

Passe uma sequência de datas AAAAMMdd e ela será convertida em número de segundos desde a época (com um pouco de atenção por estar nos limites do dia). Então você poderá subtrair os dois.

today=`echo 20110210 | awk -f convdate.awk`
then=`echo 20001231 | awk -f convdate.awk`
sincethen=`expr $today - $then`
10
Arcege

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

Existe um truque desajeitado com touch que funciona para verificar se uma data tem pelo menos n dias no passado:

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

(Observe que esse código pode ser desativado em um se o horário de verão for iniciado ou interrompido no intervalo e o script for executado antes da 01:00.)

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

A instalação das ferramentas GNU pode ser a maneira menos trabalhosa.

13

Eu tentaria usar o comando date que faz parte do POSIX, por isso está praticamente em todo lugar. ATUALIZAÇÃO: Infelizmente, parece que -d não faz parte da data POSIX e provavelmente não existe no Solaris. Portanto, isso provavelmente não responderá à pergunta dos OPs.

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

Agora d1 E d2 São números inteiros que correspondem a segundos desde a época unix. Assim, para obter a diferença entre os dois, subtraímos ($((d1-d2)) no bash) e nos escondemos em quaisquer unidades que desejamos. Os dias são os mais fáceis:

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

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

11
Steven D

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

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

O -i especifica o formato de entrada.

8
hroptatyr

É provável que o Perl esteja instalado e é fácil o suficiente obter módulos de CPAN , instalá-los no diretório inicial e consulte-os no seu programa. Nesse caso, o módulo Date :: Calc possui um Delta_Days subrotina que ajudará.

4
glenn jackman

Wrt 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 um sistema Solaris "compatível com GNU" quando configuram um novo host. Me bate por que.

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

No Solaris 10

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

No Solaris 11

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

Faça isso se não estiver instalado:

pkg install // solaris/file/gnu-coreutils
3
peterh

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 como "gawk", mas diz "no GNU tools". Gawk tem aritmética de data.

2

pitão:

 from datetime import datetime as dt
 a = dt(2010, 9, 9)
 b = dt(2000, 10, 10)
 print (a - b).days
2
akira

1. Defina data1 e data2 em %j formato do dia do ano (001..366)

[email protected]:~$ date1=`date -d 20100909 +%j` 
[email protected]:~$ date2=`date -d 20001010 +%j`

2. Calcule a diferença com expr

[email protected]:~$ datediff=`expr $date2 - $date1`

. Portanto, a resposta é 32 dias

[email protected]:~$ echo $datediff days
32 days
[email protected]:~$ 

... ou solução de uma linha

[email protected]:~$ echo $(( $(date -d 20001010 +%j) - $(date -d 20100909 +%j) )) days
32 days
[email protected]:~$ 

o

[email protected]:~$ expr $(date -d 20001010 +%j) - $(date -d 20100909 +%j)
32
[email protected]:~$

o

[email protected]:~$ expr `date -d 20001010 +%j` - `date -d 20100909 +%j`
32
[email protected]:~$ 
1
Sabrina

Você pode usar o awk biblioteca Velour 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
0
Steven Penny

Com a 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
0
OlivierOR