ubuntuusers.de

Zeitangaben addieren

Status: Gelöst | Ubuntu-Version: Ubuntu MATE 20.04 (Focal Fossa)
Antworten |

CarstenHa

Avatar von CarstenHa

Anmeldungsdatum:
1. Mai 2020

Beiträge: 147

Hallo,

Ich möchte im Skript mehrere Zeitangaben addieren. Ich dachte mir die Zeiten in Sekunden umrechnen, addieren und dann mit printf das Ergebnis ausgeben. Folgendes habe ich in eine Schleife gepackt (Variable mov_time ist jeweils die ermittelte Zeit im Format hh:mm:ss):

1
2
3
4
mov_hours="$(($(echo $mov_time | sed 's/\(^[[:digit:]]*\):.*/\1/') * 3600))"
mov_min="$(($(echo $mov_time | sed 's/^[[:digit:]]*:\([[:digit:]]*\):.*/\1/') * 60))"
mov_sec="$(echo $mov_time | sed 's/^[[:digit:]]*:[[:digit:]]*:\([[:digit:]]*\)/\1/')"
mov_sum=$((${mov_sum} + ${mov_sec} + ${mov_hours} + ${mov_min}))

Anschliessend gebe ich die Gesamtzeit aus mit:

1
printf 'Gesamtzeit: %02dh:%02dm:%02ds\n' $((${mov_sum}/3600)) $((${mov_sum}%3600/60)) $((${mov_sum}%60))

Das funktioniert auch super, allerdings frage ich mich, ob man das nicht vereinfachen kann. Gibt es z.B. ein Tool um einfach Zeiten zu addieren?

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17622

Wohnort: Berlin

Du kannst das Date-Kommando nutzen. %s gibt die Sekunden seit 1.1.1970 aus:

1
2
3
4
5
6
7
8
xubuntu@xubuntu:~$ a=$(date -d "1970/01/01 08:46:12" +%s)
xubuntu@xubuntu:~$ b=$(date -d "1970/01/01 16:23:02" +%s)
xubuntu@xubuntu:~$ echo $a
31572
xubuntu@xubuntu:~$ echo $b
58982
xubuntu@xubuntu:~$ echo $((a+b))
90554

In ein Zeiformat kann man wieder mit @ umwandeln, aber da ist wohl Deine Modulooperation näher an dem, was Du brauchst:

1
2
xubuntu@xubuntu:~$ date -d @$((a+b))
Fr 2. Jan 01:09:14 UTC 1970

Wenn die Gesamtzeit aber immer im Jahr 1970 bleibt ist die Formatierung mit date vielleicht einfacher.

1
date --help

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13216

CarstenHa schrieb:

Ich möchte im Skript mehrere Zeitangaben addieren.

Was genau willst Du denn erreichen? Geht es darum, auf eine Tageszeit in HH:MM:SS eine Dauer in HH:MM:SS zu addieren und auf eine neue Tageszeit zu kommen?

Ich dachte mir die Zeiten in Sekunden umrechnen, addieren und dann mit printf das Ergebnis ausgeben. Folgendes habe ich in eine Schleife gepackt (Variable mov_time ist jeweils die ermittelte Zeit im Format hh:mm:ss):

Und was steckt in mov_sum?

Das funktioniert auch super, allerdings frage ich mich, ob man das nicht vereinfachen kann. Gibt es z.B. ein Tool um einfach Zeiten zu addieren?

Es wäre natürlich hilfreich zu wissen, was Deine Eingabe ist (also der Inhalt von mov_time). Wenn das dasselbe Format hat, könntest Du in der bash so etwas machen:

1
2
deltas=(${mov_time//[^0-9]/ })
date -d "$mov_sum + ${deltas[0]} hour + ${deltas[1]} minute + ${deltas[2]} second" +%T

oder, in POSIX Shells

1
2
m=${mov_time#*:}
date -d "$mov_sum + ${mov_time%%:*} hour + ${m%:*} minute + ${mov_time##*:} second" +%T

CarstenHa

(Themenstarter)
Avatar von CarstenHa

Anmeldungsdatum:
1. Mai 2020

Beiträge: 147

Nein, ich möchte nur mehrere Zeiten addieren, also z.B. 01:17:10 + 02:08:01 = 03:25:11

mov_time habe ich in eine Schleife gepackt und die Variable enthält dann den jeweiligen Zeitwert hh:mm:ss

Diese Werte in mov_time sollen praktisch alle addiert werden.

Ich habe alle Werte in Sekunden umgerechnet. mov_sum rechnet diese Sekunden zusammen (Also mov_hours enthält z.B. die Stunden umgerechnet in Sekunden usw.).

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17622

Wohnort: Berlin

CarstenHa schrieb:

Nein, ich möchte nur mehrere Zeiten addieren, also z.B. 01:17:10 + 02:08:01 = 03:25:11

Und was sagst Du zu meinem Ansatz? Nicht klar geworden?

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
seksum=0
zeiten=(08:46:12 16:23:02)
for zeit in ${zeiten[@]} 
do
    seks=$(date -d "1970/01/01 $zeit" +%s)
    ((seksum+=seks))
done
res=$(date -d @$seksum)
echo $res

# Bei Bedarf Stunden/Minuten/Sekunden auseinanderschneiden, 
# Stunden evtl. in Tage umrechnen (Wochen, Monate, Jahre, Äonen)

CarstenHa

(Themenstarter)
Avatar von CarstenHa

Anmeldungsdatum:
1. Mai 2020

Beiträge: 147

user_unknown schrieb:

Und was sagst Du zu meinem Ansatz? Nicht klar geworden?

Jetzt bin ich gerade ein bisschen verwirrt. Wenn ich deine Zeiten zusammenrechne, komme ich auf 25:09:14. Das Ergebnis von $res ist Fr 2. Jan 00:09:14 CET 1970. Wie die Zeit vergeht 😀

dingsbums

Anmeldungsdatum:
13. November 2010

Beiträge: 3790

Du willst Zeitspannen addieren, keine Zeiten im eigentlichen Sinne.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#!/bin/bash

zeitspanne1="01:17:10"
zeitspanne2="02:08:55"


std1=$(echo $zeitspanne1 | cut -d ':' -f 1 | sed 's#^0##')
min1=$(echo $zeitspanne1 | cut -d ':' -f 2 | sed 's#^0##')
sek1=$(echo $zeitspanne1 | cut -d ':' -f 3 | sed 's#^0##')

std2=$(echo $zeitspanne2 | cut -d ':' -f 1 | sed 's#^0##')
min2=$(echo $zeitspanne2 | cut -d ':' -f 2 | sed 's#^0##')
sek2=$(echo $zeitspanne2 | cut -d ':' -f 3 | sed 's#^0##')

summe_sek=$(( sek1 + sek2 ))
if [ $summe_sek -gt 59 ];then
   summe_sek=$(( summe_sek - 60 ))
   if  [ $summe_sek -lt 10 ];then
      summe_sek="0$summe_sek"
   fi
   aufschlag_min=1
else
   aufschlag_min=0
fi


summe_min=$(( min1 + min2 + aufschlag_min ))
if [ $summe_min -gt 59 ];then
   summe_min=$(( summe_min - 60 ))
   if  [ $summe_min -lt 10 ];then
      summe_min="0$summe_min"
   fi
   aufschlag_std=1
else
   aufschlag_std=0
fi


summe_std=$(( std1 + std2 + aufschlag_std ))

echo "summe der zeitspannen ist $summe_std:$summe_min:$summe_sek"

Ausgabe ist

summe der zeitspannen ist 3:26:05

Ich habe im Beispiel extra den zweiten Sekunden-Ausgangswert etwas erhöht, damit der Überlauf > 59 zum Tragen kommt.

Nachtrag:

Die Anpassungen für Stunden-Summen > 24 darfst du eigenständig ergänzen. 😎

CarstenHa

(Themenstarter)
Avatar von CarstenHa

Anmeldungsdatum:
1. Mai 2020

Beiträge: 147

dingsbums schrieb:

Du willst Zeitspannen addieren, keine Zeiten im eigentlichen Sinne.

Oh ja, ich muss mich bei Euch entschuldigen ich habe das Thema falsch beschrieben.

CarstenHa

(Themenstarter)
Avatar von CarstenHa

Anmeldungsdatum:
1. Mai 2020

Beiträge: 147

Ich hab das jetzt mal wie folgt gemacht:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#!/bin/bash

zeitlist=(01:17:10 02:08:55 23:55:01)

for zeit in ${zeitlist[@]} ; do
  zeit_hoursinsec="$(($(echo "$zeit" | cut -f1 -d: | sed 's/^0//') * 3600))"
  zeit_mininsec="$(($(echo "$zeit" | cut -f2 -d: | sed 's/^0//') * 60))"
  zeit_sec="$(echo "$zeit" | cut -f3 -d: | sed 's/^0//')"
  ges_zeit=$((${ges_zeit} + ${zeit_hoursinsec} + ${zeit_mininsec} + ${zeit_sec}))
done

printf 'Gesamtzeitspanne:  %02dh:%02dm:%02ds\n' $((${ges_zeit}/3600)) $((${ges_zeit}%3600/60)) $((${ges_zeit}%60))

Das Ergebnis ist übrigens:

1
Gesamtzeitspanne:  27h:21m:06s

Ich hab mal wieder eine Menge gelernt. Danke an Euch alle!

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17622

Wohnort: Berlin

CarstenHa schrieb:

user_unknown schrieb:

Und was sagst Du zu meinem Ansatz? Nicht klar geworden?

Jetzt bin ich gerade ein bisschen verwirrt. Wenn ich deine Zeiten zusammenrechne, komme ich auf 25:09:14. Das Ergebnis von $res ist Fr 2. Jan 00:09:14 CET 1970. Wie die Zeit vergeht 😀

Ja, @date zählt ab 1.1.1970.

Ich hatte es auch in meinem Beitrag von 14:44 bereits gezeigt.

1
date  +"%j %r" -d @$seksum 

gibt die Zahl der Tage mit aus aber läuft nach einem Jahr über.

Deswegen habe ich auf die Formatierung der Ausgabe verwiesen - vielleicht bleibt ja auch alles < 24h, vielleicht wird es größer als ein Jahr. Das hast Du ja nicht verraten.

Wenn die Gesamtzeit aber immer im Jahr 1970 bleibt ist die Formatierung mit date vielleicht einfacher. date --help

Antworten |