Calcular a diferença no tempo durante vários dias

1

Eu tenho visto muitas perguntas e exemplos mostrando como calcular a diferença em dois tempos, convertendo os tempos em época, e depois convertendo a diferença em segundos ... No entanto, qual é a melhor maneira de calcular a diferença no tempo? que pode durar vários dias em dias de $ DIA, $ HOUR, hora (s), minuto (s) de $ MIN e segundos (s) de $ SEC?

Para o meu propósito, estou usando o formato de data, data + "% m /% d /% y% T" (17/08/18 09:03:31).

Digamos que minha primeira data é 15/08/18 16:22:05 e a segunda é 17/08/18 09:03:31. Como posso calcular a diferença fazendo ecoar "A diferença é de 1 dia (s), 16, horas, 41 minutos e 26 segundos".

Mas também, com o mesmo script, como é possível reconhecer se a diferença de tempo é menor que um dia para não informar "A diferença é 0 dia ..."?

EDIT: Eu tenho um roteiro principalmente trabalhando abaixo, no entanto, há muita coisa acontecendo para preservar a formatação adequada. Tudo parece funcionar além dos espaços e vírgulas apropriados, dependendo se um valor é igual a zero ...

A ideia é formatá-lo com "e" no local apropriado ao remover valores iguais a "0" ...

Então, todos os valores:     02: 05: 23: 44     2 dias, 5 horas, 23 minutos e 44 segundos

Sem horas:     02: 00: 23: 44     2 dias, 23 minutos e 44 segundos

Sem segundos:     02: 05: 23: 00     2 dias, 5 horas e 23 segundos

Eu tive isso tão perto daqui a pouco, mas com certas leituras, ele quebrou. Alguma ajuda na formatação de como eu gostaria? O roteiro também é uma bagunça longa ... Qualquer ajuda na limpeza seria legal. Eu gostaria de ver como torná-lo mais eficiente.

#!/bin/bash
TIME1="08/17/2018 11:36:40"
TIME2="08/17/2018 12:37:41"
SEC1='date +%s -d "${TIME1}"'
SEC2='date +%s -d "${TIME2}"'
DIFF='expr ${SEC2} - ${SEC1}'

CONVERTTIME() {
  ((d=${1}/86400))
  ((h=(${1}%86400)/3600))
  ((m=(${1}%3600)/60))
  ((s=${1}%60))

  #DAYS
  if [ $d -eq 1 ]; then
    DAYLABEL=day
  else
    DAYLABEL=days
  fi
  DAYCOMMA=", "
  if [[ $d -gt 0 || $h && $m && $s -eq 0 ]]; then
    DAYCOMMA=""
  fi
  DAYTEXT="$d $DAYLABEL$DAYCOMMA"
  if [ $d -eq 0 ]; then
    DAYTEXT=
  else
    if [ $h -eq 0 ]; then
      DAYTEXT="$d $DAYLABEL$DAYCOMMA"
    fi
  fi
  #HOURS
  if [ $h -eq 1 ]; then
    HOURLABEL=hour
  else
    HOURLABEL=hours
  fi
  HOURCOMMA=", "
  if [[ $h -gt 0 || $m && $s -eq 0 ]]; then
    HOURCOMMA=""
  fi
  HOURTEXT="$h $HOURLABEL$HOURCOMMA"
  if [ $h -eq 0 ]; then
    HOURTEXT=""
  else
    if [ $m -eq 0 ]; then
      HOURTEXT="$h $HOURLABEL$HOURCOMMA"
    fi
  fi
  #MINUTES
  if [ $m -eq 1 ]; then
    MINLABEL=minute
  else
    MINLABEL=minutes
  fi
  MINCOMMA=", "
  if [[ $m -gt 0 || $s -eq 0 ]]; then
    MINCOMMA=""
  fi  
  MINTEXT="$m $MINLABEL$MINCOMMA"
  if [ $m -eq 0 ]; then
    MINTEXT=""
  else
    if [ $s -eq 0 ]; then
      MINTEXT="$d $MINLABEL$MINCOMMA"
    fi
  fi
  #SECONDS
  if [ $s -eq 1 ]; then
    SECLABEL=second
  else
    SECLABEL=seconds
  fi
  SECTEXT="$s $SECLABEL"
  if [ $s -eq 0 ]; then
    SECTEXT=""
  fi

  ANDHOUR=
  ANDMIN=
  ANDSEC=
  if [[ $d && $h && $m && $s -gt 0 || $d && $h && $s -gt 0 || $d && $m && $s -gt 0 || $h && $m && $s -gt 0 || $d && $s -gt 0 || $h && $s -gt 0 || $m && $s -gt 0 ]]; then
    ANDSEC="and "
  else
    #days hours AND minutes
    #days AND minutes
    #hours AND minutes
    if [[ $d && $h && $m -gt 0 || $d && $m -gt 0 || $h && $m -gt 0 ]]; then
      ANDMIN="and "  
    else
      #days AND hours
      if [[ $d && $h -gt 0 ]]; then
        ANDHOUR="and "
      fi
    fi  
  fi
  echo -e "$DAYTEXT$ANDHOUR$HOURTEXT$ANDMIN$MINTEXT$ANDSEC$SECTEXT"
}
echo
echo "TIME DIFFERENCE: $(CONVERTTIME $DIFF)"
echo
    
por eptesicus 17.08.2018 / 15:12

1 resposta

1

Em algumas linhas (assumindo a data do GNU):

$ diff=$(($(date -ud '08/17/18 09:03:31' +'%s') - $(date -ud '08/15/18 16:22:05' +'%s')))
$ days=$(($(date -ud @$diff +'%-j')-1)) 
$ date -ud @"$diff" +"$days"'-day(s) %H:%M:%S'
1-day(s) 16:41:26

Válido até (aproximadamente) 365 dias.

Como um script:

#!/bin/sh

tosec(){ secs=$(date -ud "$1" +'%s'); }

tosec "$1"; sec1=$secs 
tosec "$2"; sec2=$secs
diff=$((sec2-sec1))
eval "$(date -ud "@$diff" +'days=%-j time=%H:%M:%S')"
printf '%s\n' "$((days-1))-day(s) $time"

Chame como:

$ ./script '08/15/18 16:22:05'   '08/17/18 09:03:31'
    
por 17.08.2018 / 19:00

Tags