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.
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.
Antworten:
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
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
+%T
Format Stunden: Minuten: Sekunden verwenden date +%T "1970-01-01 + ${seconds} seconds"
, um 21:33:09
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'
}
convert $s
, um eine hübsche Ausgabe zu erhalten.
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 date
Befehl in einem anderen Unterbefehl $(date -d ... )
, um die Stunden, Minuten und Sekunden für eine bestimmte Anzahl von Sekunden zu generieren.
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.
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, printf
da 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
printf
diese %(datefmt)T
Notation beginnend mit bash-4.2-alpha eingeführt hat.
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
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.