Sekunden
Um die verstrichene Zeit (in Sekunden) zu messen, benötigen wir:
- eine Ganzzahl, die die Anzahl der verstrichenen Sekunden und darstellt
- eine Möglichkeit, eine solche Ganzzahl in ein verwendbares Format zu konvertieren.
Ein ganzzahliger Wert der verstrichenen Sekunden:
Konvertieren Sie eine solche Ganzzahl in ein verwendbares Format
Der Bash Internal printf
kann das direkt tun:
$ TZ=UTC0 printf '%(%H:%M:%S)T\n' 12345
03:25:45
ähnlich
$ elapsedseconds=$((12*60+34))
$ TZ=UTC0 printf '%(%H:%M:%S)T\n' "$elapsedseconds"
00:12:34
aber dies wird für eine Dauer von mehr als 24 Stunden ausfallen, als wir tatsächlich eine Wanduhr Zeit drucken, nicht wirklich eine Dauer:
$ hours=30;mins=12;secs=24
$ elapsedseconds=$(( ((($hours*60)+$mins)*60)+$secs ))
$ TZ=UTC0 printf '%(%H:%M:%S)T\n' "$elapsedseconds"
06:12:24
Für die Liebhaber von Details von bash-hackers.org :
%(FORMAT)T
gibt die Datums- / Uhrzeitzeichenfolge aus, die sich aus der Verwendung von FORMAT als Formatzeichenfolge für ergibt strftime(3)
. Das zugehörige Argument ist die Anzahl der Sekunden seit Epoche oder -1 (aktuelle Zeit) oder -2 (Shell-Startzeit). Wenn kein entsprechendes Argument angegeben wird, wird standardmäßig die aktuelle Uhrzeit verwendet.
Vielleicht möchten Sie einfach anrufen, textifyDuration $elpasedseconds
wo textifyDuration
sich noch eine weitere Implementierung des Dauerdrucks befindet:
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)"
}
GNU-Datum.
Um die formatierte Zeit zu erhalten, sollten wir ein externes Tool (GNU-Datum) auf verschiedene Arten verwenden, um eine Länge von fast einem Jahr zu erreichen, einschließlich Nanosekunden.
Mathe innerhalb des Datums.
Es ist keine externe Arithmetik erforderlich. Führen Sie alles in einem Schritt aus date
:
date -u -d "0 $FinalDate seconds - $StartDate seconds" +"%H:%M:%S"
Ja, 0
die Befehlszeichenfolge enthält eine Null. Es wird gebraucht.
Dies setzt voraus, dass Sie den date +"%T"
Befehl in einen date +"%s"
Befehl ändern können , damit die Werte in Sekunden gespeichert (gedruckt) werden.
Beachten Sie, dass der Befehl auf Folgendes beschränkt ist:
- Positive Werte von
$StartDate
und $FinalDate
Sekunden.
- Der Wert in
$FinalDate
ist größer (später) als $StartDate
.
- Zeitunterschied kleiner als 24 Stunden.
- Sie akzeptieren ein Ausgabeformat mit Stunden, Minuten und Sekunden. Sehr einfach zu ändern.
- Es ist akzeptabel, -u UTC-Zeiten zu verwenden. Um "DST" und Ortszeitkorrekturen zu vermeiden.
Wenn Sie müssen die Verwendung 10:33:56
Zeichenfolge, na ja, konvertiert es nur Sekunden,
auch könnten das Wort Sekunden als sec abgekürzt werden:
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"
Beachten Sie, dass die Sekundenzeitumrechnung (wie oben dargestellt) relativ zum Beginn "dieses" Tages (heute) ist.
Das Konzept könnte folgendermaßen auf Nanosekunden erweitert werden:
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"
Wenn längere Zeitdifferenzen (bis zu 364 Tage) berechnet werden müssen, müssen wir den Jahresbeginn (einige) als Referenz und den Formatwert %j
(die Tageszahl im Jahr) verwenden:
Ähnlich zu:
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
Leider müssen wir in diesem Fall 1
EINS manuell von der Anzahl der Tage abziehen . Der Datumsbefehl zeigt den ersten Tag des Jahres als 1. Nicht so schwierig ...
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[@]}"
Die Verwendung einer langen Anzahl von Sekunden ist hier gültig und dokumentiert:
https://www.gnu.org/software/coreutils/manual/html_node/Examples-of-date.html#Examples-of-date
Busybox-Datum
Ein Tool, das in kleineren Geräten verwendet wird (eine sehr kleine ausführbare Datei, die installiert werden muss): Busybox.
Stellen Sie entweder einen Link zur Busybox mit dem Namen Datum her:
$ ln -s /bin/busybox date
Verwenden Sie es dann, indem Sie dies aufrufen date
(platzieren Sie es in einem PATH-enthaltenen Verzeichnis).
Oder machen Sie einen Alias wie:
$ alias date='busybox date'
Das Busybox-Datum hat eine nette Option: -D, um das Format der Eingabezeit zu erhalten. Das eröffnet viele Formate, die als Zeit verwendet werden können. Mit der Option -D können wir die Zeit 10:33:56 direkt konvertieren:
date -D "%H:%M:%S" -d "10:33:56" +"%Y.%m.%d-%H:%M:%S"
Und wie Sie aus der Ausgabe des obigen Befehls sehen können, wird angenommen, dass der Tag "heute" ist. So starten Sie die Zeit in die Epoche:
$ 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
Das Busybox-Datum kann sogar die Uhrzeit (im obigen Format) ohne -D empfangen:
$ date -u -d "1970.01.01-$string1" +"%Y.%m.%d-%H:%M:%S"
1970.01.01-10:33:56
Und das Ausgabeformat könnte sogar Sekunden seit der Epoche betragen.
$ date -u -d "1970.01.01-$string1" +"%s"
52436
Für beide Male und ein wenig Bash-Mathe (Busybox kann die Mathe noch nicht machen):
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 ))
Oder formatiert:
$ date -u -D "%s" -d "$(( t2 - t1 ))" +"%H:%M:%S"
00:02:14
time
Befehl nicht verwenden ?