Czy w bashu można łatwo sformatować sekundy jako czas czytelny dla człowieka?
Nie chcę formatować go jako daty, ale jako liczbę dni / godzin / minut itp.
Czy w bashu można łatwo sformatować sekundy jako czas czytelny dla człowieka?
Nie chcę formatować go jako daty, ale jako liczbę dni / godzin / minut itp.
Odpowiedzi:
Możesz użyć czegoś takiego:
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
}
Przykłady:
$ displaytime 11617
3 hours 13 minutes and 37 seconds
$ displaytime 42
42 seconds
$ displaytime 666
11 minutes and 6 seconds
Najłatwiejszym i najczystszym sposobem jest ta jedna linijka (tutaj przy założeniu GNU date
):
Jeśli liczba sekund wynosi, powiedz:
seconds=123456789 # as in one of the answers above
eval "echo $(date -ud "@$seconds" +'$((%s/3600/24)) days %H hours %M minutes %S seconds')"
-> wyjście: 1428 days 21 hours 33 minutes 09 seconds
+%T
formatu Godziny: Minuty: Sekundy, aby to date +%T "1970-01-01 + ${seconds} seconds"
uzyskać21:33:09
Zasługa Stéphane Gimenez ale jeśli ktoś chciałby, aby wyświetlić sekund tylko wtedy, gdy okres ten wynosi mniej niż minutę tutaj jest moja wersja zmodyfikowana, że używam (również ze stałym liczby mnogiej):
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
}
Alternatywny przykład w 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
aby uzyskać niezłe wyniki.
Zrobiłbym to w ten sposób:
$ 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
$
Oto jeden linijka powyżej, podzielony, aby łatwiej było zrozumieć:
$ seconds=123456789
$ echo $((seconds/86400))" days"\
$(date -d "1970-01-01 + $seconds seconds" "+%H hours %M minutes %S seconds")
W powyższym wyrażam echo wyjścia innego polecenia, które jest uruchamiane wewnątrz polecenia $( ... )
podrzędnego. To polecenie podrzędne robi to, obliczając liczbę dni (sekundy / 86400), a następnie używa date
polecenia w innym poleceniu podrzędnym $(date -d ... )
, aby wygenerować godziny, minuty i sekundy dla określonej liczby sekund.
Zmodyfikowałem funkcję displaytime powyżej ... w następujący sposób:
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
}
ponieważ zawsze chcę widzieć HH: MM: SS, nawet jeśli są zerami.
Opieram się na odpowiedzi atti, która spodobała mi się jako pomysł.
Możesz to zrobić za pomocą wbudowanego basha, printf
który zajmie kilka sekund od epoki jako argument. Nie trzeba widelca, aby uruchomić date
.
Musisz ustawić strefę czasową na UTC, printf
ponieważ formatuje ona czas w lokalnej strefie czasowej, a jeśli nie jesteś w czasie UTC, otrzymasz błędną odpowiedź.
$ 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
W moim czasie lokalnym (obecnie NZDT - +1300) odpowiedź jest błędna, jeśli nie ustawię strefy czasowej
$ seconds=123456789
$ printf "%d days %(%H hours %M minutes %S seconds)T\n" $((seconds/86400)) $seconds
1428 days 09 hours 33 minutes 09 seconds
Z ustawieniem strefy czasowej i bez
$ 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
wprowadził tę %(datefmt)T
notację zaczynając od bash-4.2-alpha.
Tutaj jeden
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
Wydajność:
4d 9h:7m:24s
date --date '@1005454800'
daje ci Sun Nov 11 00:00:00 EST 2001
, czyli 1005454800 sekund po epoce Uniksa. Możesz go sformatować za pomocą opcji data + FORMAT.