Topic: Problema con calcolo differenza di tempo tra due date ------ RISOLTO  (Letto 207 volte)

0 Utenti e 1 Visitatore stanno visualizzando questo topic.

Offline iBooma

  • python unicellularis
  • *
  • Post: 13
  • Punti reputazione: 0
    • Mostra profilo
Ciao a tutti, chiedo scusa se il mio primo post non sta nella sezione giusta o è stato già trattato, ho provato a cercare discussioni simili ma non ne ho trovate.
Premessa: Sto facendo una sorta di marcatempo per le officine, il programma consiste nel caricare in un db le info di una lavorazione tra cui il tempo di inizio lavoro prelevato dal timestamp, così come eventuali pause e riprese di lavoro e relativa chiusura. lo scopo è quello di avere l'effettiva durata della riparazione.
Il tutto quando funzionerà correttamente verrà completatato con delle scatoline con arduino e lettore rfid per scrivere i dati sul db dall'officina mentre con python vorrei gestire la parte di controllo da pc, quindi prelevare i dati dal db e mandarli all'app o sul sito poi vedrò ... Comunque scusate se mi sono dilungato vado al dunque:
Prelevo i miei timestamp dal db per fare il calcolo :

def calcola():
   
    seleziona_inizio = ("SELECT inizio_lavoro FROM tempo_lavorazioni WHERE numero_commessa = %s")
    valore_i = (commessa_entry.get(),)
    cursore.execute(seleziona_inizio, valore_i)
    inizio = str(cursore.fetchone())
   
   
    seleziona_fine = ("SELECT fine_lavoro FROM tempo_lavorazioni WHERE numero_commessa = %s")
    valore_f = (commessa_entry.get(),)
    cursore.execute(seleziona_fine, valore_f)
    fine = str(cursore.fetchone())

    print(inizio,"inizio")
    print(fine,"fine")
   

questo è il risultato:

    ('23/01/2023, 02:37:48',) inizio
    ('23/01/2023, 02:38:24',) fine

dopo cerco di calcolare il tempo trascorso tra queste due date,  provo questo:

    tempo_inizio = time.strptime(inizio, "%d-%m-%Y, %H:%M:%S")
    tempo_fine = time.strptime(fine, "%d-%m-%Y, %H:%M:%S")
    differenza = tempo_fine - tempo_inizio
    print(differenza,"Differenza")

ma mi restituisce il seguente errore:

raise ValueError("time data %r does not match format %r" %
ValueError: time data "('23/01/2023, 02:37:48',)" does not match format '%d-%m-%Y, %H:%M:%S'
 

mi sembra di capire che le "" e le () mi diano fastidio .....

ero partito da una base funzionante:

import datetime

    avvio= datetime.datetime(2020, 10, 20, 8, 3, 23)
    chiusura= datetime.datetime(2020, 10, 20, 11, 22, 54)

    print(avvio,"Avvio")
    print(chiusura,"Chiusura")

    intervallo = chiusura - avvio
    print(intervallo,"Intervallo")
risultato:
   2020-10-20 08:03:23 Avvio
   2020-10-20 11:22:54 Chiusura
   3:19:31 Intervallo

così funziona ma io il timestamp lo metto sul db e lo prelevo quando mi serve fare il calcolo. ho provato diverse prove anche cambiando la configurazione dei record  lato db(datetime, timestamp, text) , ma non riesco a capire dove e cosa sto sbagliando.

Ringrazio chiunque voglia aiutarmi, e scusatemi se vi sto chiedendo cose probabilmente banali per la maggior parte di voi ....   8)


   






   
« Ultima modifica: Gennaio 24, 2023, 01:19 da iBooma »

Offline nuzzopippo

  • python sapiens
  • *****
  • Post: 670
  • Punti reputazione: 0
    • Mostra profilo
Re:Problema con calcolo differenza di tempo tra due date
« Risposta #1 il: Gennaio 23, 2023, 07:03 »
Strano il primo errore che ricevi perché, a giudicare da questo Tuo print

    print(inizio,"inizio")
    print(fine,"fine")
questo è il risultato:
    ('23/01/2023, 02:37:48',) inizio
    ('23/01/2023, 02:38:24',) fine

"inizio" e "fine" sono due tuple, dovresti ricevere un diverso errore
Python 3.10.6 (main, Nov 14 2022, 16:10:14) [GCC 11.3.0] on linux
Type "help", "copyright", "credits" or "license()" for more information.
import time
t_inizio = ('23/01/2023, 02:37:48',)
t_fine = ('23/01/2023, 02:38:24',)
print(type(t_inizio), type(t_fine))
<class 'tuple'> <class 'tuple'>
tempo_inizio = time.strptime(t_inizio, "%d-%m-%Y, %H:%M:%S")
Traceback (most recent call last):
  File "/usr/lib/python3.10/idlelib/run.py", line 578, in runcode
    exec(code, self.locals)
  File "<pyshell#4>", line 1, in <module>
  File "/usr/lib/python3.10/_strptime.py", line 562, in _strptime_time
    tt = _strptime(data_string, format)[0]
  File "/usr/lib/python3.10/_strptime.py", line 317, in _strptime
    raise TypeError(msg.format(index, type(arg)))
TypeError: strptime() argument 0 must be str, not <class 'tuple'>

L'errore che ricevi è causato dal carattere separatore di data, che nelle stringhe presentate è "/" mentre nella stringa di formato è "-"
str_inizio = t_inizio[0]
str_fine = t_fine[0]
print(type(str_inizio), str_inizio, type(str_fine), str_fine)
<class 'str'> 23/01/2023, 02:37:48 <class 'str'> 23/01/2023, 02:38:24
tempo_inizio = time.strptime(str_inizio, "%d-%m-%Y, %H:%M:%S")
Traceback (most recent call last):
  File "/usr/lib/python3.10/idlelib/run.py", line 578, in runcode
    exec(code, self.locals)
  File "<pyshell#8>", line 1, in <module>
  File "/usr/lib/python3.10/_strptime.py", line 562, in _strptime_time
    tt = _strptime(data_string, format)[0]
  File "/usr/lib/python3.10/_strptime.py", line 349, in _strptime
    raise ValueError("time data %r does not match format %r" %
ValueError: time data '23/01/2023, 02:37:48' does not match format '%d-%m-%Y, %H:%M:%S'

per ottenere una conversione valida dovresti, quindi, utilizzare una adeguata stringa di formattazione
tempo_inizio = time.strptime(str_inizio, "%d/%m/%Y, %H:%M:%S")
                     
temp_fine = time.strptime(str_fine, "%d/%m/%Y, %H:%M:%S")

così la conversione ha luogo ma qui sorge un altro problema, ciò che ottieni dalle conversioni sono due oggetti "struct_time"
print(tempo_inizio, temp_fine)
                     
time.struct_time(tm_year=2023, tm_mon=1, tm_mday=23, tm_hour=2, tm_min=37, tm_sec=48, tm_wday=0, tm_yday=23, tm_isdst=-1) time.struct_time(tm_year=2023, tm_mon=1, tm_mday=23, tm_hour=2, tm_min=38, tm_sec=24, tm_wday=0, tm_yday=23, tm_isdst=-1)

Che non supportano direttamente l'operatore di sottrazione
differenza = temp_fine - tempo_inizio
                     
Traceback (most recent call last):
  File "/usr/lib/python3.10/idlelib/run.py", line 578, in runcode
    exec(code, self.locals)
  File "<pyshell#12>", line 1, in <module>
TypeError: unsupported operand type(s) for -: 'time.struct_time' and 'time.struct_time'

Vi sarebbero varie manipolazioni possibili ma non mi sembra il caso di complicarsi la vita, utilizzando un modulo dedicato alle "ore" su dati che coinvolgono data e ora e c'è il modulo "datetime" per trattare direttamente tali dati, prova ad importare datetime invece di time. applicandolo sulle stringhe dati ottenute, una cosa del genere
from datetime import datetime
inizio = datetime.strptime(str_inizio, "%d/%m/%Y, %H:%M:%S")
fine = datetime.strptime(str_fine, "%d/%m/%Y, %H:%M:%S")
differenza = fine - inizio
print(differenza)
0:00:36
differenza.total_seconds()
36.0

Come puoi vedere, potrai anche ottenere direttamente i secondi occorsi per la lavorazione che sono il risultato che credo Ti serva

Offline iBooma

  • python unicellularis
  • *
  • Post: 13
  • Punti reputazione: 0
    • Mostra profilo
Re:Problema con calcolo differenza di tempo tra due date
« Risposta #2 il: Gennaio 23, 2023, 11:09 »
Ciao @nuzzopippo, grazie per la tua risposta. Tutto molto chiaro non capisco perchè continua a darmi questo errore:

raise ValueError("time data %r does not match format %r" %
ValueError: time data "('23-01-2023, 10:00:09',)" does not match format '%d-%m-%Y, %H:%M:%S

riporto qui la "select" per richiamare i dati :

def calcola():
   
    seleziona_inizio = ("SELECT inizio_lavoro FROM tempo_lavorazioni WHERE numero_commessa = %s")
    valore_i = (commessa_entry.get(),)
    cursore.execute(seleziona_inizio, valore_i)
    inizio = str(cursore.fetchone())
   
   
    seleziona_fine = ("SELECT fine_lavoro FROM tempo_lavorazioni WHERE numero_commessa = %s")
    valore_f = (commessa_entry.get(),)
    cursore.execute(seleziona_fine, valore_f)
    fine = str(cursore.fetchone())

successivamente :

from datetime import datetime

   
    print(inizio,  "inizio")
    print(fine, "fine")
    tempo_inizio = datetime.strptime(inizio, "%d-%m-%Y, %H:%M:%S")
    tempo_fine = datetime.strptime(fine, "%d-%m-%Y, %H:%M:%S")
   
    differenza = tempo_fine - tempo_inizio
    print(differenza,"Differenza")


questo è il risultato del print inizio e fine

('23-01-2023, 10:00:09',) inizio
('23-01-2023, 10:02:06',) fine

sembra tutto ok eppure continua a darmi errore di mismatch ma a me sembra identici quei dati .....


« Ultima modifica: Gennaio 23, 2023, 20:47 da iBooma »

Offline GlennHK

  • python sapiens sapiens
  • ******
  • Post: 1.720
  • Punti reputazione: 1
    • Mostra profilo
    • La Tana di GlennHK
Re:Problema con calcolo differenza di tempo tra due date
« Risposta #3 il: Gennaio 23, 2023, 12:44 »
Ciao, intanto ti consiglio di formattare il codice usando l'apposita funzione perché così è illeggibile.

Secondo, cos'è "cursore"? Hai visto cosa restituisce una query di quel tipo?

Tu fai questo:
  • ricevi una tupla contenente un timestamp da db, supponiamo 2023-01-23T10:00:09 (uso ISO 8601 per non introdurre ambiguità)
  • la trasformi in stringa usando str, ottenendo ('23-01-2023, 10:00:09',)
  • usi strptime su una stringa in quel modo, che NON rispetta il formato che gli hai specificato, perché "('23-01-2023, 10:00:09',)" != "23-01-2023, 10:00:09"
Lascio a te le considerazioni del caso su quale parte sia quella sbagliata.

Offline iBooma

  • python unicellularis
  • *
  • Post: 13
  • Punti reputazione: 0
    • Mostra profilo
Re:Problema con calcolo differenza di tempo tra due date
« Risposta #4 il: Gennaio 23, 2023, 17:06 »
Ciao GlennHK, intanto ti ringrazio per l'intervento.

ho cercato di seguire i consigli che mi hanno dato ma il mio problema è proprio questo non riesco a ottenere dal db un formato corretto per operare con le date.
ho letto troppe fonti diverse e credo di aver fatto un po' di confusione, sono giorni che provo e riprovo ma non ne sto uscendo.

lato db:
i record inizio e fine ho provato a settarli sia come txt che come datatime che come timstamp, ma mi ritrovo sempre che la variabile che vado a processare per l'operazione matematica è  così  "('23-01-2023, 10:00:09',)" invece di essere così  "23-01-2023, 10:00:09". nel caso utilizzo sul db il record tipo datetime invece nella varaibile inizio o fine mi ritrovo questo : "(datetime.datetime(2023, 1, 23, 16, 29, 17),)"

pensavo che avendo l'orario su una stringa e utilizzando datetime.strptime (che richiede appunto una stringa) avevo risolto, ma non riesco a formattare la stringa nel modo corretto.

aiuto ....  :confused: :confused:

Offline nuzzopippo

  • python sapiens
  • *****
  • Post: 670
  • Punti reputazione: 0
    • Mostra profilo
Re:Problema con calcolo differenza di tempo tra due date
« Risposta #5 il: Gennaio 23, 2023, 21:34 »
...pensavo che avendo l'orario su una stringa e utilizzando datetime.strptime (che richiede appunto una stringa) avevo risolto, ma non riesco a formattare la stringa nel modo corretto...

Il resulset di una query è una lista di tuple, named-tuple se non vado errato, una singola riga dati è una tupla e come tale va trattata, per accedere al singolo elemento di una tupla puoi usare l'indice posizionale dell'elemento desiderato.
Sbrigativamente, prendendo il codice da Te postato in precedenza, l'istruzione
inizio = str(cursore.fetchone())

deve diventare
inizio = cursore.fetchone()[0]

Ciò per leggere il primo (e unico) valore contenuto nella riga dati, tale valore, nel caso da Te esemplificato è una stringa contenente un time-stamp formattato, che potrai utilizzare con le metodologie indicate, stessa cosa per il dato "fine"

Offline iBooma

  • python unicellularis
  • *
  • Post: 13
  • Punti reputazione: 0
    • Mostra profilo
Re:Problema con calcolo differenza di tempo tra due date
« Risposta #6 il: Gennaio 24, 2023, 00:17 »
...pensavo che avendo l'orario su una stringa e utilizzando datetime.strptime (che richiede appunto una stringa) avevo risolto, ma non riesco a formattare la stringa nel modo corretto...

Il resulset di una query è una lista di tuple, named-tuple se non vado errato, una singola riga dati è una tupla e come tale va trattata, per accedere al singolo elemento di una tupla puoi usare l'indice posizionale dell'elemento desiderato.
Sbrigativamente, prendendo il codice da Te postato in precedenza, l'istruzione
inizio = str(cursore.fetchone())

deve diventare
inizio = cursore.fetchone()[0]

Ciò per leggere il primo (e unico) valore contenuto nella riga dati, tale valore, nel caso da Te esemplificato è una stringa contenente un time-stamp formattato, che potrai utilizzare con le metodologie indicate, stessa cosa per il dato "fine"

Grazie, grazie grazie  :batti5:
inizio = cursore.fetchone()[0]

questo era il pezzetto che mi mancava, devo dire che lo avevo anche provato ma mettevo l'indice
  • sulla variabile inizio mandavo in print e mi usciva solo la parentesi e non riuscivo a capire. Ora ho capito ! 8)




Offline iBooma

  • python unicellularis
  • *
  • Post: 13
  • Punti reputazione: 0
    • Mostra profilo
Re:Problema con calcolo differenza di tempo tra due date ----- RISOLTO
« Risposta #7 il: Gennaio 24, 2023, 00:58 »
riporto la funzione calcola in grado di sommare 4 intervalli di tempo (Avvio, Pausa, Riavvio, fine), e scrivere nel DB la durata totale di una riparazione.
Sicuramente c'è qualche print di troppo ma solo per controllo... e sicuramente si può scrivere meglio anzi accetto qualsiasi commento a riguardo
 
Grazie di nuovo per l'aiuto  :angel:


def calcola():
   
    seleziona_inizio = ("SELECT inizio_lavoro FROM tempo_lavorazioni WHERE numero_commessa = %s")
    valore_i = (commessa_entry.get(),)
    cursore.execute(seleziona_inizio, valore_i)
    inizio = cursore.fetchone()[0]

    seleziona_fine = ("SELECT fine_lavoro FROM tempo_lavorazioni WHERE numero_commessa = %s")
    valore_f = (commessa_entry.get(),)
    cursore.execute(seleziona_fine, valore_f)
    fine = cursore.fetchone()[0]
   
    seleziona_pausa = ("SELECT pausa_lavoro FROM tempo_lavorazioni WHERE numero_commessa = %s")
    valore_p = (commessa_entry.get(),)
    cursore.execute(seleziona_pausa, valore_p)
    pausa = cursore.fetchone()[0]

    seleziona_riavvio = ("SELECT riavvio_lavoro FROM tempo_lavorazioni WHERE numero_commessa = %s")
    valore_r = (commessa_entry.get(),)
    cursore.execute(seleziona_riavvio, valore_r)
    riavvio = cursore.fetchone()[0]

   
    print(inizio,"inizio")
    print(fine,"fine")
    print(pausa,"Pausa")
    print(riavvio,"Riavvio")


    from datetime import datetime
    import time
   
    #CALCOLO DA INIZIO A PRIMA PAUSA
   
    tempo_inizio = datetime.strptime(inizio, "%d-%m-%Y, %H:%M:%S")
    tempo_pausa = datetime.strptime(pausa, "%d-%m-%Y, %H:%M:%S")
    print(tempo_inizio,  "str_inizio")
    print(tempo_pausa, "str_pausa")
    differenza_1 = tempo_pausa - tempo_inizio
    print(differenza_1,"Differenza 1")
   
    secondi_totali_1= differenza_1.total_seconds()
    print(secondi_totali_1,"Secondi Totali 1")
    print(type(differenza_1),"Differenza 1")
    print(type(secondi_totali_1), "Secondi Totali 1")

    #CALCOLO DA RIAVVIO A FINE

    tempo_riavvio = datetime.strptime(riavvio, "%d-%m-%Y, %H:%M:%S")
    tempo_fine = datetime.strptime(fine, "%d-%m-%Y, %H:%M:%S")
    print(tempo_riavvio,  "str_riavvio")
    print(tempo_fine, "str_fine")
    differenza_2 = tempo_fine - tempo_riavvio
    print(differenza_2,"Differenza 2")
   
    secondi_totali_2= differenza_2.total_seconds()
    print(secondi_totali_2, "Secondi Totali 2")
    print(type(differenza_2),"Differenza 2")
    print(type(secondi_totali_2), "Secondi Totali 2")

    # SOMMO I DUE INTERVALLI

    durata_totale = str(differenza_1 + differenza_2)
    print(durata_totale, "Durata Totale")

    secondi_totali= secondi_totali_1 + secondi_totali_2
    print(secondi_totali, "Secondi Totali")


    # SCRIVO NEL DB LA DURATA TOTALE
    durata_sql = "UPDATE tempo_lavorazioni SET durata = %s WHERE numero_commessa = %s"
    valori_d = (durata_totale, commessa_entry.get())
    cursore.execute(durata_sql, valori_d)
    db.commit()
   


questo il risultato:


23-01-2023, 23:16:02 inizio
23-01-2023, 23:21:27 fine
23-01-2023, 23:17:34 Pausa
23-01-2023, 23:18:33 Riavvio
2023-01-23 23:16:02 str_inizio
2023-01-23 23:17:34 str_pausa
0:01:32 Differenza 1
92.0 Secondi Totali 1
<class 'datetime.timedelta'> Differenza 1
<class 'float'> Secondi Totali 1
2023-01-23 23:18:33 str_riavvio
2023-01-23 23:21:27 str_fine
0:02:54 Differenza 2
174.0 Secondi Totali 2
<class 'datetime.timedelta'> Differenza 2
<class 'float'> Secondi Totali 2
0:04:26 Durata Totale
266.0 Secondi Totali

Offline nuzzopippo

  • python sapiens
  • *****
  • Post: 670
  • Punti reputazione: 0
    • Mostra profilo
Re:Problema con calcolo differenza di tempo tra due date
« Risposta #8 il: Gennaio 24, 2023, 08:19 »
...
inizio = cursore.fetchone()[0]

questo era il pezzetto che mi mancava, devo dire che lo avevo anche provato ma mettevo l'indice
  • sulla variabile inizio mandavo in print e mi usciva solo la parentesi e non riuscivo a capire. Ora ho capito ! 8)
Occhio, l'istruzione va bene per il caso specifico di un singolo elemento nella risposta, nel caso di più elementi devi procedere diversamente : o ti memorizzi la tupla in una variabile e poi estrai ciò che Ti serve con gli indici oppure la scomponi direttamente nella lettura nelle variabili che Ti occorrono.
Se non hai chiaro come si fa cerca in rete documentazione ed esempi sull'uso delle tuple.

Offline GlennHK

  • python sapiens sapiens
  • ******
  • Post: 1.720
  • Punti reputazione: 1
    • Mostra profilo
    • La Tana di GlennHK
Re:Problema con calcolo differenza di tempo tra due date ------ RISOLTO
« Risposta #9 il: Gennaio 24, 2023, 08:32 »
Ma che database usi? Perché devi fare parse delle date?

Offline iBooma

  • python unicellularis
  • *
  • Post: 13
  • Punti reputazione: 0
    • Mostra profilo
Re:Problema con calcolo differenza di tempo tra due date
« Risposta #10 il: Gennaio 24, 2023, 11:41 »
...
inizio = cursore.fetchone()[0]

questo era il pezzetto che mi mancava, devo dire che lo avevo anche provato ma mettevo l'indice
  • sulla variabile inizio mandavo in print e mi usciva solo la parentesi e non riuscivo a capire. Ora ho capito ! 8)
Occhio, l'istruzione va bene per il caso specifico di un singolo elemento nella risposta, nel caso di più elementi devi procedere diversamente : o ti memorizzi la tupla in una variabile e poi estrai ciò che Ti serve con gli indici oppure la scomponi direttamente nella lettura nelle variabili che Ti occorrono.
Se non hai chiaro come si fa cerca in rete documentazione ed esempi sull'uso delle tuple.



Si si mi è tutto chiaro ..... Grazie ancora  :ok:

Offline iBooma

  • python unicellularis
  • *
  • Post: 13
  • Punti reputazione: 0
    • Mostra profilo
Re:Problema con calcolo differenza di tempo tra due date ------ RISOLTO
« Risposta #11 il: Gennaio 24, 2023, 12:21 »
Ma che database usi? Perché devi fare parse delle date?

al momento ho maria db con xampp, quando avrò finito passero a un db sql su un dominio, intanto volevo farlo funzionare il tutto. 

Offline GlennHK

  • python sapiens sapiens
  • ******
  • Post: 1.720
  • Punti reputazione: 1
    • Mostra profilo
    • La Tana di GlennHK
Re:Problema con calcolo differenza di tempo tra due date ------ RISOLTO
« Risposta #12 il: Gennaio 24, 2023, 12:54 »
mariadb ha il tipo date, datetime e timestamp: https://mariadb.com/kb/en/date-and-time-data-types/


Perché non usarli?

Offline iBooma

  • python unicellularis
  • *
  • Post: 13
  • Punti reputazione: 0
    • Mostra profilo
Re:Problema con calcolo differenza di tempo tra due date ------ RISOLTO
« Risposta #13 il: Gennaio 25, 2023, 12:19 »
mariadb ha il tipo date, datetime e timestamp: https://mariadb.com/kb/en/date-and-time-data-types/


Perché non usarli?
Ciao GlennHK, sinceramente ora che sto approfondendo e studiando la questione me lo sto chiedendo anche io, Sicuramente ho fatto un po di confusione all'inizio e tra i vari tentativi fatti stavo raggiugendo l'obbiettivo con i record del db impostati come stringhe, quindi mi sono ritrovato a fare queste operazioni doppie diverse volte  ( trasforma dati tipo time_structur in stringa e viceversa ) . In tutta questa confusione apparente ho però appreso diversi concetti e ho le basi per approfondire .... ripulilrò il codice appena possibile  e renderò tutto più lineare ...  mi farebbe piacere avere il tuo giudizio... 

Grazie come sempre per il tuo tempo. :)