[Python-es] Opinión sobre función para obtener una duración (de tiempo)

Dani dani en damufo.eu
Mar Mar 16 12:44:31 EDT 2021


Hola: 🙂

Estoy intentando de validar una duración (tiempo) introducido en una 
caja de texto.
Lo que trato de validar es una duración no una hora.
Las duraciones tienen una precisión de centésimas de segundo por lo que 
la función devuelve las centésimas de la duración.

El caso es que creo que me he complicado algo y seguro que se puede 
hacer mejor.
Es por aprender, porque la función tal como está me funciona (o eso creo).

Para la validación se tienen en cuenta dos formas de introducir las 
duraciones, una con puntuación y otra sin.
Para la separación de decimales se puede introducir tanto coma como punto.
El tiempo mínimo son 10,00 (10 s).
El tiempo máximo son 23:59:59
Con «tiempo» me estoy refiriendo a duraciones.

Mis dudas preguntas son:
Creéis que son demasiado laxos los formatos a introducir?
Por ejemplo, no tengo claro si esto
'1:6.44'
sería mejor NO validarlo?

O las introducciones que acaban en «:» como por ejemplo:
:16:
16:
las cuales actualmente tienen resultados válidos.



Saludos y gracias por la atención.


duraciones.py

# -*- coding: utf-8 -*-


values = (
     ':34',  # error
     '000044',  # error
     '000000',  # error
     '106.44',  # error
     '106.4',  # error
     '1:06.44',  # 1:06,44
     '1:6.44',  # 1:06,44
     '1:6.4',  # 1:06,40
     '16.44',  # 16,44
     '16:44',  # 16,44
     '16.4',  # 16,40
     '16.',  # 16,00
     ':16: ',  # 16,00
     '16: ',  # 16:00.00
     '.16: ',  # error por inferior a 10,00
     '34.15',  # 34,15
     '3415',  # 34,15
     '1:30:44',  # 1:30:44,00
     '13044',  # 1:30,44
     '1:60.44',  # error
     'A1b:6.44', # error
     '00:00.44', # error por ser inferior a 10,00
     '00:10.4', # 10,44
     '59:00.44',  # 59:00,44
     '0:59:00.44',  # 59:00,44
     '23:59:59.99',  # 23:59:59,99
     '10.00',  # 10,00
     '12:34:15',  # 12:34:15,00
     '123415',  # 12:34,15
     '2:01:23.56',  # 2:01:23,56
     '2012356',  # 2:01:23,56
     '23:01:23.56',  # 23:01:23,56
     '23:01:23:56',  # esto pasa a 23:01:23:56.00 por lo que da error al 
pasar el valor máximo 23:59:59.99
     '25:01:23.56',  # error, el valor máximo es 23:59:59,99
     '25012356',  # error, el valor máximo es 23:59:59,99
     )




def validate(value):
     '''
     value is a duration string
     return hundredths integer
     '''
     hundredths = 0
     tempo_formatado = ''
     value = value.strip()
     error = ''
     partes = []
     if value.isdigit():  # valida introducción de marca sólo con números
         digits = value
         len_digits = len(digits)
         if len_digits == 4:
             partes = [digits[-2:], digits[-4:-2]]
         elif len_digits in (5, 6):
             partes = [digits[-2:], digits[-4:-2], digits[-6:-4]]
         elif len_digits in (7, 8):
             partes = [digits[-2:], digits[-4:-2], digits[-6:-4], 
digits[-8:-6]]
         else:
             partes = []
             error = 'Exceeded the maximum number of digits.'
     else:  # valida introducción de marca con puntuación
         # busca a última puntuación e separa
         for pos in range((len(value)-1), -1, -1):
             if value[pos] in ('.',','):
                 partes = value.split(value[pos])
                 # repair void
                 for x, i in enumerate(partes):
                     if not i:
                         partes[x] = '00'
                 if len(partes) > 2:
                     error = 'value mal formed'
                     partes = []
                 else:
                     partes = partes[0].split(":") + [partes[1], ]
                     break
             elif value[pos] == ':':
                 partes = value.split(":")
                 # repair void
                 for x, i in enumerate(partes):
                     if not i:
                         partes[x] = '00'
                 partes.append('00')
                 break
         if len(partes) in (2, 3, 4):
             partes = partes[::-1]  # reverse
             for x, i in enumerate(partes):
                 if i.isdigit():
                     if len(i) == 1:
                         if x == 0:
                             partes[x] = '%s0' % i
                         else:
                             partes[x] = '0%s' % i
                 else:
                     partes = []
                     error = 'ilegal characters'
                     break
         else:
             error = 'value mal formed'
             partes = []
     while len(partes) > 1 and int(partes[-1]) == 0:
         partes.pop()

     if len(partes) in (2, 3, 4):
         # check partes ranges
         for x, i in enumerate(partes):
             if x == 0:
                 if int(i) > 99:
                     error = 'value out range'
                     break
                 else:
                     hundredths += int(i)
             elif x == 1:
                 if int(i) > 59:
                     error = 'value out range'
                     hundredths = 0
                     break
                 else:
                     hundredths += int(i) * 100
             elif x == 2:
                 if int(i) > 59:
                     error = 'value out range'
                     hundredths = 0
                     break
                 else:
                     hundredths += int(i) * 6000
             elif x == 3:
                 if int(i) > 23:
                     error = 'value out range'
                     hundredths = 0
                     break
                 else:
                     hundredths += int(i) * 360000
         if hundredths:
             tempo_formatado = partes[::-1]
             tempo_formatado[0] = str(int(tempo_formatado[0]))  # quita 
o cero incial
             tempo_formatado = ':'.join(tempo_formatado)
             tempo_formatado = tempo_formatado[::-1].replace(':', ',', 
1)[::-1]

     print('{} -> {} -> {}  {}'.format(value, tempo_formatado, 
hundredths, error))
     return hundredths

for value in values:
     validate(value)


-- 
Dani
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <https://mail.python.org/pipermail/python-es/attachments/20210316/7184bbb2/attachment.html>


Más información sobre la lista de distribución Python-es