Vereinfachung gesucht

Code-Stücke können hier veröffentlicht werden.
Antworten
WvonRiedi
User
Beiträge: 36
Registriert: Mittwoch 20. Januar 2021, 20:46

Ich habe eine csv Datei die Zeiten enthält.
Datum;Distanz in km;Cal;Zeit In Bewegung
2022-01-06;10.00;481;01:01:10
2022-01-08;10.00;381;01:01:10
2022-02-20;10.00;205;01:01:10
2022-03-30;10.00;457;01:01:10
2022-03-30;10.00;450;01:01:10

Den Code fürs zusammenrechnen habe ich auch schon erfragt in diesem Forum :P .
Nun möchte ich jeden Monat berechnen. Das geht soweit, jedoch schreibe ich den Code für jeden Monat einzeln. Geht das auch einfacher?

Herzlichen Dank für ne Idee. Werner

Code: Alles auswählen

import csv 
from datetime import datetime, timedelta
import os
    
def main():
    zähler =0
    monat_in_zahl = "00"
    A = 0
    januar_Total = 0
    januar_Totalger = 0    
    januar_h = 0
    januar_m = 0
    januar_s = 0
          
    with open("Monat_versuch.csv ", "r") as Datei:

            for line in Datei:      
                line_splitted = line.strip().split(";")
              
                if line_splitted[0] == "Datum":
                    pass
                else:
                    datum_ganz=(line_splitted[0])  
                    monat_in_zahl = datum_ganz[5:7]

    # -- Januar einlesen ---                    
                    if monat_in_zahl == "01" : 
                           #--- Hier berechnen 

                        A = line_splitted[3] #Zeit auslesen
                        C = len(A)# Länge der Zeit anschauen 01:01:01 , 1:01:01 oder 40:15

                        if C == 8: #Wenn Zeit acht stellig dann 01:01:01
                            timeA = datetime.strptime(A, "%H:%M:%S")
                            januar_h = timeA.hour + januar_h
                            januar_m = timeA.minute + januar_m
                            januar_s = timeA.second + januar_s

                        elif  C == 7:#Wenn Zeit sieben stellig dann 1:01:01
                            
                            timeA = datetime.strptime(A, "%H:%M:%S")
                            januar_h = timeA.hour + januar_h
                            januar_m = timeA.minute + januar_m
                            januar_s = timeA.second + januar_s

                        elif C == 5:  #Wenn Zeit fünf stellig dann 40:15
                            timeA = datetime.strptime(A, "%M:%S")
                            januar_m = timeA.minute + januar_m
                            januar_s = timeA.second + januar_s

                        elif C == 4:  #Wenn Zeit vier stellig dann 4:15 
                            timeA = datetime.strptime(A, "%M:%S")
                            januar_m = timeA.minute + januar_m
                            januar_s = timeA.second + januar_s

            d1 = timedelta(hours=januar_h,minutes=januar_m, seconds=januar_s)

            secs = d1.total_seconds()# timedelta in Sekunden umrechnen

            # Zeit manuell formatieren
            januar_h2 = int(secs // 3600) # Stunden
            januar_m2 = int(secs % 3600) // 60 # Minuten
            januar_s2 = int(secs % 60) # Sekunden

            januar_time = str(januar_h2) + ":" + str(januar_m2) + ":" + str(januar_s2)
            
if __name__ == "__main__":
    main() 
print(januar_time)
#print(februar_time)
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Du importierst doch schon csv, warum benutzt du es nicht?

Aber die Vereinfachung ist einfach, benutze pandas zum einlesen:
https://realpython.com/python-csv/
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Variablennamen werden komplett klein geschrieben.
Einbuchstabige Variablen sind wenig aussagekräftig. Was soll jemand mit `A` oder `C` anfangen?
Wenn die erste Zeile in einer Schleife anders behandelt wird, wie die anderen, dann macht man diese Behandlung vor der for-Schleife.
Es scheint sich im Zeiträume zu handeln, da ist datetime leider die falsche Klasse. Deshalb ist es in Deinem Fall wahrscheinlich am sinnvollesten, alles in Sekunden zu rechnen.
Dagegen ist das Datum ein wirkliches Datum, wofür es das datetime-Modul gibt.
Zum Lesen gibt es das csv-Modul.
Du definierst am Anfang etliche Variablen, die dann nirgends gebraucht werden oder gleich mit einem anderen Wert überschrieben zu werden. Variablen benutzt man einfach.
Die Werte für die einzelnen Monate sammelt man in einer passenden Datenstruktur.

Code: Alles auswählen

import csv 
from datetime import datetime
from collections import defaultdict

def parse_duration(duration):
    parts = map(int, duration.split(':'))
    if len(parts) == 3:
        return (parts[0] * 24 + parts[1]) * 60 + parts[2]
    else:
        return parts[1] * 60 + parts[2]

def main():
    durations = defaultdict(int)          
    with open("Monat_versuch.csv ", newline="") as file:
        reader = csv.reader(file, delimiter=";")
        header = next(reader)
        for line in reader:
            date = datetime.strptime(line[0], '%Y-%m-%d').date()
            duration = parse_duration(line[3])
            durations[date.replace(day=1)] += duration
    
    for date, duration in sorted(durations.items()):
        hours, seconds = divmod(duration, 3600)
        minutes, seconds = divmod(duration, 60)
        print(f"{date:%Y-%m}: {hours}:{minutes:02d}:{seconds:02d}")

if __name__ == "__main__":
    main() 
WvonRiedi
User
Beiträge: 36
Registriert: Mittwoch 20. Januar 2021, 20:46

Danke für die rasche Antwort.
Wenn die erste Zeile....
Werde ich mir merken, danke.
Du definierst am Anfang ...... Variablen benutzt man einfach.
Hab ich mir auch gedacht, jedoch erscheint bei mir dann eine Fehlermeldung: "local variable 'januar_h' referenced before assignment"

So wie Dein Code habe ich mir das vorgestellt. Bei mir erscheint eine Fehler Meldung: if len(parts) == 3: " object of type 'map' has no len()".

Mal schauen ob ich es hinkriege dieses problem zu lösen.
Werner
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Da hat er nur was vergessen, müsste so lauten:

Code: Alles auswählen

parts = list(map(int, duration.split(':')))
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
WvonRiedi
User
Beiträge: 36
Registriert: Mittwoch 20. Januar 2021, 20:46

Danke für den entscheidenden Tipp.

Vielleicht intressierte es ja einmal einen anderen Anfänger wie mich. Der Code von Sirius3 hat kleine Fehler.

Code: Alles auswählen

import csv 
from datetime import datetime
from collections import defaultdict

def parse_duration(duration):
    parts = list(map(int, duration.split(':')))
    if len(parts) == 3:
    	# return (parts[0] * 24 + parts[1]) * 60 + parts[2]      (* 60 statt 24)
        return (parts[0] * 60 + parts[1]) * 60 + parts[2]
    else:
    # return parts[1] * 60 + parts[2]    ([0] +[1])
        return parts[0] * 60 + parts[1]

def main():
    durations = defaultdict(int)          
    with open("Monat_versuch.csv ", newline="") as file:
        reader = csv.reader(file, delimiter=";")
        header = next(reader)
        for line in reader:
            date = datetime.strptime(line[0], '%Y-%m-%d').date()
            duration = parse_duration(line[3])
            durations[date.replace(day=1)] += duration
    
    for date, duration in sorted(durations.items()):
       # Dieser Code geht so nicht zeigt z.B. 215 Sekunden an
       
        #hours, seconds = divmod(duration, 3600)
        #minutes, seconds = divmod(duration, 60)
        
        # so hab ich es gelöst
        
        hours= int(duration // 3600) # Stunden
        minutes = int(duration % 3600) // 60 # Minuten
        seconds= int(duration % 60) # Sekunden

        
        print(f"{date:%Y-%m}: {hours}:{minutes}:{seconds}")

if __name__ == "__main__":
    main() 
Antworten