Sekunden als Tage / Stunden / Minuten / Sekunden anzeigen?

31

Ist es möglich, Sekunden einfach als lesbare Zeit in Bash zu formatieren?

Ich möchte es nicht als Datum formatieren, sondern als Anzahl der Tage / Stunden / Minuten usw.

Tyilo
quelle
Könnten Sie bitte ein oder mehrere Beispiele nennen?
gabe.
1
Wollen Sie damit sagen, dass Sie ein Intervall oder ein Datum seit der Epoche haben?
Paul Tomblin

Antworten:

41

Sie können so etwas verwenden:

function displaytime {
  local T=$1
  local D=$((T/60/60/24))
  local H=$((T/60/60%24))
  local M=$((T/60%60))
  local S=$((T%60))
  (( $D > 0 )) && printf '%d days ' $D
  (( $H > 0 )) && printf '%d hours ' $H
  (( $M > 0 )) && printf '%d minutes ' $M
  (( $D > 0 || $H > 0 || $M > 0 )) && printf 'and '
  printf '%d seconds\n' $S
}

Beispiele:

$ displaytime 11617
3 hours 13 minutes and 37 seconds
$ displaytime 42
42 seconds
$ displaytime 666
11 minutes and 6 seconds
Stéphane Gimenez
quelle
11

Der einfachste und sauberste Weg ist dieser eine Liner (hier unter der Annahme von GNU date):

Wenn die Anzahl der Sekunden ist, sagen Sie:

seconds=123456789 # as in one of the answers above

eval "echo $(date -ud "@$seconds" +'$((%s/3600/24)) days %H hours %M minutes %S seconds')"

-> Ausgabe: 1428 days 21 hours 33 minutes 09 seconds

Jacques
quelle
Wenn Ihre Dauer immer kürzer als ein Tag ist, können Sie das +%TFormat Stunden: Minuten: Sekunden verwenden date +%T "1970-01-01 + ${seconds} seconds", um 21:33:09
Folgendes
7

Gutschrift geht an Stéphane Gimenez, aber wenn jemand nur Sekunden anzeigen möchte, wenn ein Punkt weniger als eine Minute beträgt, ist hier meine modifizierte Version, die ich verwende (auch mit fester Pluralisierung):

converts()
{
    local t=$1

    local d=$((t/60/60/24))
    local h=$((t/60/60%24))
    local m=$((t/60%60))
    local s=$((t%60))

    if [[ $d > 0 ]]; then
            [[ $d = 1 ]] && echo -n "$d day " || echo -n "$d days "
    fi
    if [[ $h > 0 ]]; then
            [[ $h = 1 ]] && echo -n "$h hour " || echo -n "$h hours "
    fi
    if [[ $m > 0 ]]; then
            [[ $m = 1 ]] && echo -n "$m minute " || echo -n "$m minutes "
    fi
    if [[ $d = 0 && $h = 0 && $m = 0 ]]; then
            [[ $s = 1 ]] && echo -n "$s second" || echo -n "$s seconds"
    fi  
    echo
}

Ein alternatives Beispiel in POSIX:

converts(){
    t=$1

    d=$((t/60/60/24))
    h=$((t/60/60%24))
    m=$((t/60%60))
    s=$((t%60))

    if [ $d -gt 0 ]; then
            [ $d = 1 ] && printf "%d day " $d || printf "%d days " $d
    fi
    if [ $h -gt 0 ]; then
            [ $h = 1 ] && printf "%d hour " $h || printf "%d hours " $h
    fi
    if [ $m -gt 0 ]; then
            [ $m = 1 ] && printf "%d minute " $m || printf "%d minutes " $m
    fi
    if [ $d = 0 ] && [ $h = 0 ] && [ $m = 0 ]; then
            [ $s = 1 ] && printf "%d second" $s || printf "%d seconds" $s
    fi
    printf '\n'
}
dimir
quelle
Das hat sehr gut funktioniert. Ich habe die Funktion einfach in mein Skript eingefügt und ausgeführt convert $s, um eine hübsche Ausgabe zu erhalten.
Flickerfly
3

Ich würde es so machen:

$ seconds=123456789; echo $((seconds/86400))" days "$(date -d "1970-01-01 + $seconds seconds" "+%H hours %M minutes %S seconds")
1428 days 21 hours 33 minutes 09 seconds
$

Hier ist der Einzeiler oben, aufgeschlüsselt, damit es einfacher zu verstehen ist:

$ seconds=123456789
$ echo $((seconds/86400))" days"\
     $(date -d "1970-01-01 + $seconds seconds" "+%H hours %M minutes %S seconds")

Oben gebe ich die Ausgabe eines anderen Befehls wieder, der im $( ... )Unterbefehl ausgeführt wird. Dieser Unterbefehl berechnet dazu die Anzahl der Tage (Sekunden / 86400) und verwendet dann den dateBefehl in einem anderen Unterbefehl $(date -d ... ), um die Stunden, Minuten und Sekunden für eine bestimmte Anzahl von Sekunden zu generieren.

atti
quelle
2

Ich habe die Anzeigezeitfunktion oben geändert ... wie folgt:

seconds2time ()
{
   T=$1
   D=$((T/60/60/24))
   H=$((T/60/60%24))
   M=$((T/60%60))
   S=$((T%60))

   if [[ ${D} != 0 ]]
   then
      printf '%d days %02d:%02d:%02d' $D $H $M $S
   else
      printf '%02d:%02d:%02d' $H $M $S
   fi
}

weil ich immer HH: MM: SS sehen will, auch wenn sie Nullen sind.

Larry Helms
quelle
1

Ich baue auf Attis Antwort auf, die mir als Idee gefallen hat.

Sie können dies mit der eingebauten Bash tun printf, die die Sekunden seit der Epoche als Argument verwendet. Zum Laufen muss man nicht verzweigen date.

Sie müssen die Zeitzone auf UTC einstellen, printfda sie die Zeit in Ihrer lokalen Zeitzone formatiert und Sie die falsche Antwort erhalten, wenn Sie nicht in UTC sind.

$ seconds=123456789
$ TZ=UTC printf "%d days %(%H hours %M minutes %S seconds)T\n" $((seconds/86400)) $seconds
1428 days 21 hours 33 minutes 09 seconds

In meiner Ortszeit (derzeit NZDT - +1300) ist die Antwort falsch, wenn ich die Zeitzone nicht einstelle

$ seconds=123456789
$ printf "%d days %(%H hours %M minutes %S seconds)T\n" $((seconds/86400)) $seconds
1428 days 09 hours 33 minutes 09 seconds

Mit und ohne Zeitzone

$ seconds=$(( 3600 * 25))
$ printf "%d days %(%H hours %M minutes %S seconds)T\n" $((seconds/86400)) $seconds
1 days 13 hours 00 minutes 00 seconds

$ TZ=UTC printf "%d days %(%H hours %M minutes %S seconds)T\n" $((seconds/86400)) $seconds
1 days 01 hours 00 minutes 00 seconds
Bill Ryder
quelle
Beachten Sie, dass bash printfdiese %(datefmt)TNotation beginnend mit bash-4.2-alpha eingeführt hat.
Bischof
-1

Hier einer

secs=378444
echo $(($secs/86400))d $(($(($secs - $secs/86400*86400))/3600))h:$(($(($secs - $secs/86400*86400))%3600/60))m:$(($(($secs - $secs/86400*86400))%60))s

Ausgabe:

4d 9h:7m:24s
Shirish Shukla
quelle
-2

date --date '@1005454800'gibt dir Sun Nov 11 00:00:00 EST 2001, was 1005454800 Sekunden nach der Unix-Epoche ist. Sie können dies mit der Option Datum + FORMAT formatieren.

Paul Tomblin
quelle
7
Das ist ein Datum, keine Dauer, nach der die Frage gestellt wurde.
Gilles 'SO - hör auf böse zu sein'