Verwenden Sie stattdessen die Unix-Zeit date +%sund subtrahieren Sie dann, um die Differenz in Sekunden zu erhalten.
Roblogic
Antworten:
475
Bash verfügt über eine praktische SECONDSintegrierte Variable, die die Anzahl der Sekunden verfolgt, die seit dem Start der Shell vergangen sind. Diese Variable behält ihre Eigenschaften bei, wenn sie zugewiesen wird, und der nach der Zuweisung zurückgegebene Wert gibt die Anzahl der Sekunden seit der Zuweisung plus den zugewiesenen Wert an.
Sie können also einfach SECONDSvor dem Starten des zeitgesteuerten Ereignisses auf 0 setzen , einfach SECONDSnach dem Ereignis lesen und die Zeitarithmetik vor der Anzeige durchführen.
SECONDS=0# do some work
duration=$SECONDS
echo "$(($duration / 60)) minutes and $(($duration % 60)) seconds elapsed."
Da diese Lösung nicht von date +%s(einer GNU-Erweiterung) abhängt , kann sie auf alle von Bash unterstützten Systeme portiert werden.
+1. Übrigens können dateSie durch Schreiben dazu verleiten , die Zeitarithmetik für Sie durchzuführen date -u -d @"$diff" +'%-Mm %-Ss'. (Das wird $diffals Sekunden seit der Epoche interpretiert und berechnet die Minuten und Sekunden in UTC.) Das ist wahrscheinlich nicht eleganter, nur besser verschleiert. :-P
Ruakh
13
Schön und einfach. Wenn jemand Stunden braucht:echo "$(($diff / 3600)) hours, $((($diff / 60) % 60)) minutes and $(($diff % 60)) seconds elapsed."
Chus
6
Es sollte gelesen werden $(date -u +%s), um eine Rennbedingung an Daten zu verhindern, an denen die Sommerzeit umgeschaltet wird. Und hüte dich vor den bösen Schaltsekunden;)
Tino
3
@ daniel-kamil-kozar Schöner Fund. Dies ist jedoch ein bisschen zerbrechlich. Es gibt nur eine solche Variable, daher kann sie nicht rekursiv verwendet werden, um die Leistung zu messen, und noch schlimmer, wenn unset SECONDSsie weg ist:echo $SECONDS; unset SECONDS; SECONDS=0; sleep 3; echo $SECONDS
Tino
6
@ParthianShot: Es tut mir leid, dass Sie so denken. Ich glaube jedoch, dass diese Antwort das ist, was die meisten Menschen brauchen, wenn sie nach Antworten auf eine Frage wie diese suchen: um zu messen, wie viel Zeit zwischen Ereignissen vergangen ist, und nicht um die Zeit zu berechnen.
Daniel Kamil Kozar
99
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:
Es gibt zwei interne Bash-Methoden, um einen ganzzahligen Wert für die Anzahl der verstrichenen Sekunden zu ermitteln:
Bash-Variable SECONDS (wenn SECONDS nicht gesetzt ist, verliert es seine spezielle Eigenschaft).
Setzen Sie den Wert von SECONDS auf 0:
SECONDS=0
sleep 1# Process to execute
elapsedseconds=$SECONDS
Speichern des Werts der Variablen SECONDSzu Beginn:
a=$SECONDS
sleep 1# Process to execute
elapsedseconds=$(( SECONDS - a ))
Bash printf Option %(datefmt)T:
a="$(TZ=UTC0 printf '%(%s)T\n' '-1')"### `-1` is the current time
sleep 1### Process to execute
elapsedseconds=$(( $(TZ=UTC0 printf '%(%s)T\n''-1')- a ))
Konvertieren Sie eine solche Ganzzahl in ein verwendbares Format
%(FORMAT)Tgibt 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 $elpasedsecondswo textifyDurationsich noch eine weitere Implementierung des Dauerdrucks befindet:
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, 0die 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 $StartDateund $FinalDateSekunden.
Der Wert in $FinalDateist 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:56Zeichenfolge, na ja, konvertiert es nur Sekunden,
auch könnten das Wort Sekunden als sec abgekürzt werden:
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 1EINS manuell von der Anzahl der Tage abziehen . Der Datumsbefehl zeigt den ersten Tag des Jahres als 1. Nicht so schwierig ...
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):
Dies ist eine so erstaunliche Antwort, die viele Grundlagen und feine Erklärungen abdeckt. Danke dir!
Devy
Ich musste die %(FORMAT)TZeichenfolge nachschlagen, die an den printfin bash integrierten Befehl übergeben wurde. Von bash-hackers.org : Geben Sie %(FORMAT)Tdie Datums- / FORMATUhrzeitzeichenfolge aus, die sich aus der Verwendung als Formatzeichenfolge für strftime (3) ergibt. 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 Zeit verwendet . Das ist esoterisch. In diesem Fall ist %swie angegeben strftime(3)"die Anzahl der Sekunden seit der Epoche".
Wie unterscheidet sich das von meiner Lösung? Ich kann den Vorteil eines Aufrufs awkin diesem Fall wirklich nicht erkennen , da Bash die Ganzzahlarithmetik gleich gut verarbeitet.
Daniel Kamil Kozar
1
Ihre Antwort ist auch richtig. Einige Leute, wie ich, arbeiten lieber mit awk als mit Bash-Inkonsistenzen.
Dorian
2
Könnten Sie etwas mehr über die Inkonsistenzen in Bash in Bezug auf die Ganzzahlarithmetik erläutern? Ich würde gerne mehr darüber wissen, da mir nichts bekannt war.
Daniel Kamil Kozar
12
Ich habe nur danach gesucht. Ich verstehe die Kritik an dieser Antwort nicht. Ich möchte mehr als eine Lösung für ein Problem sehen. Und ich bin einer, der awkBefehle dem Bash vorzieht (wenn auch aus keinem anderen Grund, weil awk in anderen Shells funktioniert). Diese Lösung hat mir besser gefallen. Aber das ist meine persönliche Meinung.
rpsml
4
Führende Nullen: echo $ ((END-START)) | awk '{printf "% 02d:% 02d \ n", int ($ 1/60), int ($ 1% 60)}'
Ich habe nach so etwas wie Ihrer GNU- date Methode gesucht . Genius.
Haohmaru
Bitte löschen Sie meinen Kommentar ... Entschuldigung
Bill Gale
Nach der Installation dateutilsüber apt gab es keinen datediffBefehl - musste verwendet werden dateutils.ddiff.
Suzana
12
Ich möchte einen anderen Weg vorschlagen, um das Abrufen von dateBefehlen zu vermeiden . Dies kann hilfreich sein, wenn Sie bereits Zeitstempel im %TDatumsformat gesammelt haben :
ts_get_sec(){
read -r h m s <<< $(echo $1 | tr ':'' ')
echo $(((h*60*60)+(m*60)+s))}
start_ts=10:33:56
stop_ts=10:36:10
START=$(ts_get_sec $start_ts)
STOP=$(ts_get_sec $stop_ts)
DIFF=$((STOP-START))
echo "$((DIFF/60))m $((DIFF%60))s"
Wir können sogar Millisekunden auf die gleiche Weise behandeln.
ts_get_msec(){
read -r h m s ms <<< $(echo $1 | tr '.:'' ')
echo $(((h*60*60*1000)+(m*60*1000)+(s*1000)+ms))}
start_ts=10:33:56.104
stop_ts=10:36:10.102
START=$(ts_get_msec $start_ts)
STOP=$(ts_get_msec $stop_ts)
DIFF=$((STOP-START))
min=$((DIFF/(60*1000)))
sec=$(((DIFF%(60*1000))/1000))
ms=$(((DIFF%(60*1000))%1000))
echo "${min}:${sec}.$ms"
Die Millisekundenbehandlung verhält sich schlecht, wenn das Millisekundenfeld mit einer Null beginnt. Zum Beispiel gibt ms = "033" nachfolgende Ziffern von "027" an, weil das ms-Feld als oktal interpretiert wird. Wenn Sie "echo" ... "+ ms))" in ... "+ $ {ms ## + (0)})" ändern, wird dies behoben, solange "shopt -s extglob" irgendwo darüber im angezeigt wird Skript. Man sollte wahrscheinlich auch führende Nullen von h, m und s entfernen ...
Eric Towers
3
echo $(((60*60*$((10#$h)))+(60*$((10#$m)))+$((10#$s))))arbeitete für mich seit ich bekamvalue too great for base (error token is "08")
Niklas
6
Hier ist etwas Magie:
time1=14:30
time2=$( date +%H:%M )# 16:00
diff=$( echo "$time2 - $time1"| sed 's%:%+(1/60)*%g'| bc -l )
echo $diff hours
# outputs 1.5 hours
sedersetzt a :durch eine Formel, die in 1/60 konvertiert werden soll. Dann die Zeitberechnung, die von gemacht wirdbc
Hier ist eine Lösung, die nur die dateBefehlsfunktionen verwendet, die "vor" verwenden, und keine zweite Variable zum Speichern der Endzeit verwendet:
#!/bin/bash# save the current time
start_time=$( date +%s.%N )# tested program
sleep 1# the current time after the program has finished# minus the time when we started, in seconds.nanoseconds
elapsed_time=$( date +%s.%N --date="$start_time seconds ago")
echo elapsed_time: $elapsed_time
Einige Zeichenfolgenverarbeitungen können diese leeren Werte entfernen
date -ujf%s $(($(date -jf%T "10:36:10"+%s)- $(date -jf%T "10:33:56"+%s))) \
+'%-Hh %-Mm %-Ss'| sed "s/[[:<:]]0[hms] *//g"# 2m 14s
Dies funktioniert nicht, wenn Sie die frühere Zeit zuerst platzieren. Wenn Sie damit umgehen müssen, wechseln Sie $(($(date ...) - $(date ...)))zu$(echo $(date ...) - $(date ...) | bc | tr -d -)
Ich brauchte ein Zeitunterschiedsskript zur Verwendung mit mencoder(es --endposist relativ), und meine Lösung besteht darin, ein Python-Skript aufzurufen:
$ ./timediff.py 1:10:152:12:441:02:29
Sekundenbruchteile werden ebenfalls unterstützt:
$ echo "diff is `./timediff.py 10:51.6 12:44` (in hh:mm:ss format)"
diff is 0:01:52.4(in hh:mm:ss format)
und es kann Ihnen sagen, dass der Unterschied zwischen 200 und 120 1h 20m beträgt:
$ ./timediff.py 120:0200:01:20:0
und kann eine beliebige (wahrscheinlich gebrochene) Anzahl von Sekunden, Minuten oder Stunden in hh: mm: ss umwandeln
$ units
2411 units,71 prefixes,33 nonlinear units
You have:(10hr+36min+10s)-(10hr+33min+56s)You want: s
*134/0.0074626866You have:(10hr+36min+10s)-(10hr+33min+56s)You want: min
*2.2333333/0.44776119
Mir ist klar, dass dies ein älterer Beitrag ist, aber ich bin heute darauf gestoßen, als ich an einem Skript gearbeitet habe, das Datum und Uhrzeit aus einer Protokolldatei entnimmt und das Delta berechnet. Das folgende Skript ist sicherlich übertrieben, und ich empfehle dringend, meine Logik und Mathematik zu überprüfen.
#!/bin/bash
dTime=""
tmp=""#firstEntry="$(head -n 1 "$LOG" | sed 's/.*] \([0-9: -]\+\).*/\1/')"
firstEntry="2013-01-16 01:56:37"#lastEntry="$(tac "$LOG" | head -n 1 | sed 's/.*] \([0-9: -]\+\).*/\1/')"
lastEntry="2014-09-17 18:24:02"# I like to make the variables easier to parse
firstEntry="${firstEntry//-/ }"
lastEntry="${lastEntry//-/ }"
firstEntry="${firstEntry//:/ }"
lastEntry="${lastEntry//:/ }"# remove the following lines in production
echo "$lastEntry"
echo "$firstEntry"# compute days in last entryfor i in`seq 1 $(echo $lastEntry|awk '{print $2}')`;do{case"$i"in1|3|5|7|8|10|12)
dTime=$(($dTime+31));;4|6|9|11)
dTime=$(($dTime+30));;2)
dTime=$(($dTime+28));;esac}done# do leap year calculations for all years between first and last entryfor i in`seq $(echo $firstEntry|awk '{print $1}') $(echo $lastEntry|awk '{print $1}')`;do{if[ $(($i%4))-eq 0]&&[ $(($i%100))-eq 0]&&[ $(($i%400))-eq 0];then{if["$i"="$(echo $firstEntry|awk '{print $1}')"]&&[ $(echo $firstEntry|awk '{print $2}')-lt 2];then{
dTime=$(($dTime+1))}elif[ $(echo $firstEntry|awk '{print $2}')-eq 2]&&[ $(echo $firstEntry|awk '{print $3}')-lt 29];then{
dTime=$(($dTime+1))}fi}elif[ $(($i%4))-eq 0]&&[ $(($i%100))-ne 0];then{if["$i"="$(echo $lastEntry|awk '{print $1}')"]&&[ $(echo $lastEntry|awk '{print $2}')-gt 2];then{
dTime=$(($dTime+1))}elif[ $(echo $lastEntry|awk '{print $2}')-eq 2]&&[ $(echo $lastEntry|awk '{print $3}')-ne 29];then{
dTime=$(($dTime+1))}fi}fi}done# substract days in first entryfor i in`seq 1 $(echo $firstEntry|awk '{print $2}')`;do{case"$i"in1|3|5|7|8|10|12)
dTime=$(($dTime-31));;4|6|9|11)
dTime=$(($dTime-30));;2)
dTime=$(($dTime-28));;esac}done
dTime=$(($dTime+$(echo $lastEntry|awk '{print $3}')-$(echo $firstEntry|awk '{print $3}')))# The above gives number of days for sample. Now we need hours, minutes, and seconds# As a bit of hackery I just put the stuff in the best order for use in a for loop
dTime="$(($(echo $lastEntry|awk '{print $6}')-$(echo $firstEntry|awk '{print $6}'))) $(($(echo $lastEntry|awk '{print $5}')-$(echo $firstEntry|awk '{print $5}'))) $(($(echo $lastEntry|awk '{print $4}')-$(echo $firstEntry|awk '{print $4}'))) $dTime"
tmp=1for i in $dTime;do{if[ $i -lt 0];then{case"$tmp"in1)
tmp="$(($(echo $dTime|awk '{print $1}')+60)) $(($(echo $dTime|awk '{print $2}')-1))"
dTime="$tmp $(echo $dTime|awk '{print $3""$4}')"
tmp=1;;2)
tmp="$(($(echo $dTime|awk '{print $2}')+60)) $(($(echo $dTime|awk '{print $3}')-1))"
dTime="$(echo $dTime|awk '{print $1}') $tmp $(echo $dTime|awk '{print $4}')"
tmp=2;;3)
tmp="$(($(echo $dTime|awk '{print $3}')+24)) $(($(echo $dTime|awk '{print $4}')-1))"
dTime="$(echo $dTime|awk '{print $1""$2}') $tmp"
tmp=3;;esac}fi
tmp=$(($tmp+1))}done
echo "The sample time is $(echo $dTime|awk '{print $4}') days, $(echo $dTime|awk '{print $3}') hours, $(echo $dTime|awk '{print $2}') minutes, and $(echo $dTime|awk '{print $1}') seconds."
Sie erhalten folgende Ausgabe.
2012101601563720140917182402The sample time is 700 days,16 hours,27 minutes, and 25 seconds.
Ich habe das Skript ein wenig modifiziert, um es eigenständig zu machen (dh nur variable Werte festlegen), aber vielleicht kommt auch die allgemeine Idee rüber. Möglicherweise möchten Sie zusätzliche Fehler bei der Überprüfung auf negative Werte.
Ich kann die Antwort von mcaleaa nicht kommentieren, daher poste ich dies hier. Die Variable "diff" sollte sich in einem kleinen Fall befinden. Hier ist ein Beispiel.
[root@test ~]# date1=$(date +"%s"); date
WedFeb2123:00:20 MYT 2018[root@test ~]#[root@test ~]# date2=$(date +"%s"); date
WedFeb2123:00:33 MYT 2018[root@test ~]#[root@test ~]# diff=$(($date2-$date1))[root@test ~]#
Vorherige Variable wurde in Kleinbuchstaben deklariert. Dies ist passiert, wenn Großbuchstaben verwendet werden.
Hier ist meine Bash-Implementierung (mit Bits aus anderen SO ;-)
function countTimeDiff(){
timeA=$1 # 09:59:35
timeB=$2 # 17:32:55# feeding variables by using read and splitting with IFS
IFS=: read ah am as <<<"$timeA"
IFS=: read bh bm bs <<<"$timeB"# Convert hours to minutes.# The 10# is there to avoid errors with leading zeros# by telling bash that we use base 10
secondsA=$((10#$ah*60*60 + 10#$am*60 + 10#$as))
secondsB=$((10#$bh*60*60 + 10#$bm*60 + 10#$bs))
DIFF_SEC=$((secondsB - secondsA))
echo "The difference is $DIFF_SEC seconds.";
SEC=$(($DIFF_SEC%60))
MIN=$((($DIFF_SEC-$SEC)%3600/60))
HRS=$((($DIFF_SEC-$MIN*60)/3600))
TIME_DIFF="$HRS:$MIN:$SEC";
echo $TIME_DIFF;}
$ countTimeDiff 2:15:552:55:16The difference is 2361 seconds.0:39:21
time
Befehl nicht verwenden ?date +%s
und subtrahieren Sie dann, um die Differenz in Sekunden zu erhalten.Antworten:
Bash verfügt über eine praktische
SECONDS
integrierte Variable, die die Anzahl der Sekunden verfolgt, die seit dem Start der Shell vergangen sind. Diese Variable behält ihre Eigenschaften bei, wenn sie zugewiesen wird, und der nach der Zuweisung zurückgegebene Wert gibt die Anzahl der Sekunden seit der Zuweisung plus den zugewiesenen Wert an.Sie können also einfach
SECONDS
vor dem Starten des zeitgesteuerten Ereignisses auf 0 setzen , einfachSECONDS
nach dem Ereignis lesen und die Zeitarithmetik vor der Anzeige durchführen.Da diese Lösung nicht von
date +%s
(einer GNU-Erweiterung) abhängt , kann sie auf alle von Bash unterstützten Systeme portiert werden.quelle
date
Sie durch Schreiben dazu verleiten , die Zeitarithmetik für Sie durchzuführendate -u -d @"$diff" +'%-Mm %-Ss'
. (Das wird$diff
als Sekunden seit der Epoche interpretiert und berechnet die Minuten und Sekunden in UTC.) Das ist wahrscheinlich nicht eleganter, nur besser verschleiert. :-Pecho "$(($diff / 3600)) hours, $((($diff / 60) % 60)) minutes and $(($diff % 60)) seconds elapsed."
$(date -u +%s)
, um eine Rennbedingung an Daten zu verhindern, an denen die Sommerzeit umgeschaltet wird. Und hüte dich vor den bösen Schaltsekunden;)unset SECONDS
sie weg ist:echo $SECONDS; unset SECONDS; SECONDS=0; sleep 3; echo $SECONDS
Sekunden
Um die verstrichene Zeit (in Sekunden) zu messen, benötigen wir:
Ein ganzzahliger Wert der verstrichenen Sekunden:
Es gibt zwei interne Bash-Methoden, um einen ganzzahligen Wert für die Anzahl der verstrichenen Sekunden zu ermitteln:
Bash-Variable SECONDS (wenn SECONDS nicht gesetzt ist, verliert es seine spezielle Eigenschaft).
Setzen Sie den Wert von SECONDS auf 0:
Speichern des Werts der Variablen
SECONDS
zu Beginn:Bash printf Option
%(datefmt)T
:Konvertieren Sie eine solche Ganzzahl in ein verwendbares Format
Der Bash Internal
printf
kann das direkt tun:ähnlich
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:
Für die Liebhaber von Details von bash-hackers.org :
Vielleicht möchten Sie einfach anrufen,
textifyDuration $elpasedseconds
wotextifyDuration
sich noch eine weitere Implementierung des Dauerdrucks befindet: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
:Ja,
0
die Befehlszeichenfolge enthält eine Null. Es wird gebraucht.Dies setzt voraus, dass Sie den
date +"%T"
Befehl in einendate +"%s"
Befehl ändern können , damit die Werte in Sekunden gespeichert (gedruckt) werden.Beachten Sie, dass der Befehl auf Folgendes beschränkt ist:
$StartDate
und$FinalDate
Sekunden.$FinalDate
ist größer (später) als$StartDate
.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:
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:
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:
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 ...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:
Verwenden Sie es dann, indem Sie dies aufrufen
date
(platzieren Sie es in einem PATH-enthaltenen Verzeichnis).Oder machen Sie einen Alias wie:
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:
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:
Das Busybox-Datum kann sogar die Uhrzeit (im obigen Format) ohne -D empfangen:
Und das Ausgabeformat könnte sogar Sekunden seit der Epoche betragen.
Für beide Male und ein wenig Bash-Mathe (Busybox kann die Mathe noch nicht machen):
Oder formatiert:
quelle
%(FORMAT)T
Zeichenfolge nachschlagen, die an denprintf
in bash integrierten Befehl übergeben wurde. Von bash-hackers.org : Geben Sie%(FORMAT)T
die Datums- /FORMAT
Uhrzeitzeichenfolge aus, die sich aus der Verwendung als Formatzeichenfolge für strftime (3) ergibt. 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 Zeit verwendet . Das ist esoterisch. In diesem Fall ist%s
wie angegebenstrftime(3)
"die Anzahl der Sekunden seit der Epoche".So habe ich es gemacht:
Ganz einfach, nehmen Sie die Anzahl der Sekunden am Anfang, dann die Anzahl der Sekunden am Ende und drucken Sie die Differenz in Minuten: Sekunden.
quelle
awk
in diesem Fall wirklich nicht erkennen , da Bash die Ganzzahlarithmetik gleich gut verarbeitet.awk
Befehle dem Bash vorzieht (wenn auch aus keinem anderen Grund, weil awk in anderen Shells funktioniert). Diese Lösung hat mir besser gefallen. Aber das ist meine persönliche Meinung.Eine andere Option ist die Verwendung
datediff
vondateutils
( http://www.fresse.org/dateutils/#datediff ):Sie könnten auch verwenden
gawk
.mawk
1.3.4 hat auchstrftime
undmktime
aber ältere Versionen vonmawk
undnawk
nicht.Oder hier ist eine andere Möglichkeit, dies mit GNU zu tun
date
:quelle
date
Methode gesucht . Genius.dateutils
über apt gab es keinendatediff
Befehl - musste verwendet werdendateutils.ddiff
.Ich möchte einen anderen Weg vorschlagen, um das Abrufen von
date
Befehlen zu vermeiden . Dies kann hilfreich sein, wenn Sie bereits Zeitstempel im%T
Datumsformat gesammelt haben :Wir können sogar Millisekunden auf die gleiche Weise behandeln.
quelle
echo $(((60*60*$((10#$h)))+(60*$((10#$m)))+$((10#$s))))
arbeitete für mich seit ich bekamvalue too great for base (error token is "08")
Hier ist etwas Magie:
sed
ersetzt a:
durch eine Formel, die in 1/60 konvertiert werden soll. Dann die Zeitberechnung, die von gemacht wirdbc
quelle
Ab dem Datum (GNU coreutils) 7.4 können Sie jetzt -d verwenden, um zu rechnen:
Die Einheiten, die Sie verwenden können, sind Tage, Jahre, Monate, Stunden, Minuten und Sekunden:
quelle
In Anlehnung an die Antwort von Daniel Kamil Kozar, um Stunden / Minuten / Sekunden anzuzeigen:
Das vollständige Skript wäre also:
quelle
Oder wickeln Sie es ein bisschen ein
Dann funktioniert das.
quelle
Hier ist eine Lösung, die nur die
date
Befehlsfunktionen verwendet, die "vor" verwenden, und keine zweite Variable zum Speichern der Endzeit verwendet:das gibt:
quelle
quelle
date
.date
kann Ihnen den Unterschied geben und ihn für Sie formatieren (OS X-Optionen werden angezeigt)Einige Zeichenfolgenverarbeitungen können diese leeren Werte entfernen
Dies funktioniert nicht, wenn Sie die frühere Zeit zuerst platzieren. Wenn Sie damit umgehen müssen, wechseln Sie
$(($(date ...) - $(date ...)))
zu$(echo $(date ...) - $(date ...) | bc | tr -d -)
quelle
Ich brauchte ein Zeitunterschiedsskript zur Verwendung mit
mencoder
(es--endpos
ist relativ), und meine Lösung besteht darin, ein Python-Skript aufzurufen:Sekundenbruchteile werden ebenfalls unterstützt:
und es kann Ihnen sagen, dass der Unterschied zwischen 200 und 120 1h 20m beträgt:
und kann eine beliebige (wahrscheinlich gebrochene) Anzahl von Sekunden, Minuten oder Stunden in hh: mm: ss umwandeln
timediff.py:
quelle
Mit GNU
units
:quelle
Verallgemeinern der @ nisetama-Lösung unter Verwendung des GNU-Datums (vertrauenswürdiges Ubuntu 14.04 LTS):
Nachgeben:
quelle
quelle
Definieren Sie diese Funktion (z. B. in ~ / .bashrc):
Jetzt können Sie die Zeit von Teilen Ihrer Skripte messen:
Sehr nützlich, um Ausführungsengpässe zu finden.
quelle
Mir ist klar, dass dies ein älterer Beitrag ist, aber ich bin heute darauf gestoßen, als ich an einem Skript gearbeitet habe, das Datum und Uhrzeit aus einer Protokolldatei entnimmt und das Delta berechnet. Das folgende Skript ist sicherlich übertrieben, und ich empfehle dringend, meine Logik und Mathematik zu überprüfen.
Sie erhalten folgende Ausgabe.
Ich habe das Skript ein wenig modifiziert, um es eigenständig zu machen (dh nur variable Werte festlegen), aber vielleicht kommt auch die allgemeine Idee rüber. Möglicherweise möchten Sie zusätzliche Fehler bei der Überprüfung auf negative Werte.
quelle
Ich kann die Antwort von mcaleaa nicht kommentieren, daher poste ich dies hier. Die Variable "diff" sollte sich in einem kleinen Fall befinden. Hier ist ein Beispiel.
Vorherige Variable wurde in Kleinbuchstaben deklariert. Dies ist passiert, wenn Großbuchstaben verwendet werden.
Eine schnelle Lösung wäre also so
quelle
Hier ist meine Bash-Implementierung (mit Bits aus anderen SO ;-)
Nicht getestet, kann fehlerhaft sein.
quelle