sekundy
Do pomiaru upływu czasu (w sekundach) potrzebujemy:
- liczba całkowita reprezentująca liczbę upływających sekund i
- sposób na konwersję takiej liczby całkowitej na użyteczny format.
Liczba całkowita upływających sekund:
Konwertuj taką liczbę całkowitą na użyteczny format
Bash wewnętrzny printf
może to zrobić bezpośrednio:
$ TZ=UTC0 printf '%(%H:%M:%S)T\n' 12345
03:25:45
podobnie
$ elapsedseconds=$((12*60+34))
$ TZ=UTC0 printf '%(%H:%M:%S)T\n' "$elapsedseconds"
00:12:34
ale to nie powiedzie się na dłużej niż 24 godziny, ponieważ tak naprawdę drukujemy czas naścienny, a nie czas trwania:
$ hours=30;mins=12;secs=24
$ elapsedseconds=$(( ((($hours*60)+$mins)*60)+$secs ))
$ TZ=UTC0 printf '%(%H:%M:%S)T\n' "$elapsedseconds"
06:12:24
Dla miłośników szczegółów z bash-hackers.org :
%(FORMAT)T
wyświetla ciąg daty i godziny wynikający z użycia FORMATU jako ciągu formatu dla strftime(3)
. Powiązany argument to liczba sekund od Epoki lub -1 (bieżący czas) lub -2 (czas uruchamiania powłoki). Jeśli nie podano odpowiedniego argumentu, domyślnie jest używany bieżący czas.
Możesz więc zadzwonić, textifyDuration $elpasedseconds
gdzie textifyDuration
jest jeszcze jedna implementacja drukowania czasu trwania:
textifyDuration() {
local duration=$1
local shiff=$duration
local secs=$((shiff % 60)); shiff=$((shiff / 60));
local mins=$((shiff % 60)); shiff=$((shiff / 60));
local hours=$shiff
local splur; if [ $secs -eq 1 ]; then splur=''; else splur='s'; fi
local mplur; if [ $mins -eq 1 ]; then mplur=''; else mplur='s'; fi
local hplur; if [ $hours -eq 1 ]; then hplur=''; else hplur='s'; fi
if [[ $hours -gt 0 ]]; then
txt="$hours hour$hplur, $mins minute$mplur, $secs second$splur"
elif [[ $mins -gt 0 ]]; then
txt="$mins minute$mplur, $secs second$splur"
else
txt="$secs second$splur"
fi
echo "$txt (from $duration seconds)"
}
Data GNU.
Aby uzyskać sformatowany czas, powinniśmy skorzystać z zewnętrznego narzędzia (data GNU) na kilka sposobów, aby osiągnąć długość prawie roku, w tym nanosekundy.
Matematyka w dacie.
Nie ma potrzeby stosowania zewnętrznej arytmetyki, zrób to wszystko w jednym kroku date
:
date -u -d "0 $FinalDate seconds - $StartDate seconds" +"%H:%M:%S"
Tak, 0
w wierszu polecenia jest zero. To jest potrzebne.
Zakłada się, że możesz zmienić date +"%T"
polecenie na date +"%s"
polecenie, aby wartości zostały zapisane (wydrukowane) w kilka sekund.
Pamiętaj, że polecenie jest ograniczone do:
- Wartości dodatnie
$StartDate
i $FinalDate
sekundy.
- Wartość w
$FinalDate
jest większa (później) niż $StartDate
.
- Różnica czasu mniejsza niż 24 godziny.
- Akceptujesz format wyjściowy z godzinami, minutami i sekundami. Bardzo łatwa do zmiany.
- Dopuszczalne jest użycie czasów -u UTC. Aby uniknąć „DST” i korekt czasu lokalnego.
Jeśli musisz użyć 10:33:56
ciągu, cóż, po prostu przekonwertuj go na sekundy,
również słowo sekundy może być skrócone jako sec:
string1="10:33:56"
string2="10:36:10"
StartDate=$(date -u -d "$string1" +"%s")
FinalDate=$(date -u -d "$string2" +"%s")
date -u -d "0 $FinalDate sec - $StartDate sec" +"%H:%M:%S"
Zwróć uwagę, że przeliczenie czasu w sekundach (jak pokazano powyżej) odnosi się do początku „tego” dnia (dziś).
Pojęcie to można rozszerzyć na nanosekundy, takie jak to:
string1="10:33:56.5400022"
string2="10:36:10.8800056"
StartDate=$(date -u -d "$string1" +"%s.%N")
FinalDate=$(date -u -d "$string2" +"%s.%N")
date -u -d "0 $FinalDate sec - $StartDate sec" +"%H:%M:%S.%N"
Jeśli wymagane jest obliczenie dłuższych (do 364 dni) różnic czasowych, musimy użyć początku (jakiegoś) roku jako wartości odniesienia i wartości formatu %j
(numeru dnia w roku):
Podobny do:
string1="+10 days 10:33:56.5400022"
string2="+35 days 10:36:10.8800056"
StartDate=$(date -u -d "2000/1/1 $string1" +"%s.%N")
FinalDate=$(date -u -d "2000/1/1 $string2" +"%s.%N")
date -u -d "2000/1/1 $FinalDate sec - $StartDate sec" +"%j days %H:%M:%S.%N"
Output:
026 days 00:02:14.340003400
Niestety, w tym przypadku musimy ręcznie odjąć 1
JEDEN od liczby dni. Polecenie daty wyświetla pierwszy dzień roku jako 1. Nie jest to trudne ...
a=( $(date -u -d "2000/1/1 $FinalDate sec - $StartDate sec" +"%j days %H:%M:%S.%N") )
a[0]=$((10#${a[0]}-1)); echo "${a[@]}"
Wykorzystanie dużej liczby sekund jest prawidłowe i udokumentowane tutaj:
https://www.gnu.org/software/coreutils/manual/html_node/Examples-of-date.html#Examples-of-date
Data zajętości
Narzędzie używane w mniejszych urządzeniach (bardzo mały plik wykonywalny do zainstalowania): Busybox.
Utwórz link do busyboksa o nazwie data:
$ ln -s /bin/busybox date
Użyj go następnie, wywołując to date
(umieść w katalogu zawierającym ŚCIEŻKĘ).
Lub stwórz alias:
$ alias date='busybox date'
Data Busybox ma fajną opcję: -D, aby otrzymać format godziny wejściowej. Otwiera to wiele formatów, które można wykorzystać jako czas. Za pomocą opcji -D możemy bezpośrednio przekonwertować czas 10:33:56:
date -D "%H:%M:%S" -d "10:33:56" +"%Y.%m.%d-%H:%M:%S"
I jak widać na podstawie powyższego polecenia, przyjmuje się, że dzień jest „dzisiaj”. Aby uzyskać czas zaczynający się od epoki:
$ string1="10:33:56"
$ date -u -D "%Y.%m.%d-%H:%M:%S" -d "1970.01.01-$string1" +"%Y.%m.%d-%H:%M:%S"
1970.01.01-10:33:56
Data Busybox może nawet odbierać czas (w powyższym formacie) bez -D:
$ date -u -d "1970.01.01-$string1" +"%Y.%m.%d-%H:%M:%S"
1970.01.01-10:33:56
Format wyjściowy może wynosić nawet kilka sekund od epoki.
$ date -u -d "1970.01.01-$string1" +"%s"
52436
W obu przypadkach i trochę matematyki (zajęty nie potrafi jeszcze matematyki):
string1="10:33:56"
string2="10:36:10"
t1=$(date -u -d "1970.01.01-$string1" +"%s")
t2=$(date -u -d "1970.01.01-$string2" +"%s")
echo $(( t2 - t1 ))
Lub sformatowane:
$ date -u -D "%s" -d "$(( t2 - t1 ))" +"%H:%M:%S"
00:02:14
time
polecenia?