J'essaie de convertir une liste de chaînes en datetime.

Voici un exemple des données dont je traite:
x = ['59:55:00', '59:55:00', '59:58:00', '1:00:02', '1:00:05', '1:01:26']

Par exemple, la liste est censée refléter 59 minutes, 58 secondes à 1 heure, 0 minutes et 5 secondes.

Je comprends que c'est un format farfelu, mais je joue avec la main qui m'a été distribuée. Je ne sais pas comment gérer les données une fois que je suis entré dans des valeurs supérieures à 59 minutes.

J'ai essayé d'utiliser:

from datetime import datetime
for i in x:
    datetime_object = datetime.strptime(i, '%M:%S:%f')
    print(datetime_object)

Mes résultats sont:

1900-01-01 00:59:55
1900-01-01 00:59:55
1900-01-01 00:59:58
1900-01-01 00:01:00.020000
1900-01-01 00:01:00.050000
1900-01-01 00:01:01.260000

Je voudrais garder ma sortie en minutes et secondes. Par exemple, 1:01:26 serait 00:61:26

Donc, ma sortie souhaitée ressemblerait à quelque chose comme:

1900-01-01 00:59:55
1900-01-01 00:59:55
1900-01-01 00:59:58
1900-01-01 00:60:02
1900-01-01 00:60:02
1900-01-01 00:61:26

Toute aide ou conseil est grandement apprécié!

3
Tommy 27 janv. 2019 à 04:46

5 réponses

Meilleure réponse

Les objets datetime.datetime doivent prendre des paramètres qui se situent dans une certaine plage, c'est-à-dire que les minutes doivent être comprises entre 0 et 59. Cependant, vous pouvez créer une classe pour gérer ce comportement souhaité. La classe peut convertir l'entrée au format d'horodatage souhaité, stocker la chaîne d'origine et fournir une propriété to_date pour récupérer l'horodatage réel en tant qu'objet datetime.datetime:

import datetime

class Minutes:
  d = datetime.datetime.now()
  def __init__(self, _str, _year = None):
    self._val = _str
    d = datetime.datetime.now()
    self.year = _year if _year is not None else '-'.join(str(getattr(d, i)) for i in ['year', 'month', 'day'])
  @property
  def to_date(self):
    return datetime.datetime(*map(int, self.year.split('-')), *map(int, str(self).split(':')))
  def __str__(self):
    _h, _m, _s = map(int, self._val.split(':'))
    h, m, s = 0 if _h else _h, _m+(_h*60) if _h else _m, _s
    return f'{self.year} '+':'.join(str(i).zfill(2) for i in [h, m, s])
  def __repr__(self):
    return str(self)

x = ['59:55:00', '59:55:00', '59:58:00', '1:00:02', '1:00:05', '1:01:26']
new_x = [Minutes(i, '1900-01-01') for i in x]    

Production:

[1900-01-01 00:3595:00, 
 1900-01-01 00:3595:00, 
 1900-01-01 00:3598:00, 
 1900-01-01 00:60:02, 
 1900-01-01 00:60:05, 
 1900-01-01 00:61:26]
2
Ajax1234 27 janv. 2019 à 02:14

Étant donné la garantie que les données ne reviendront pas au format précédent, nous pouvons les normaliser. Pour garder les choses propres, c'est probablement mieux enveloppé dans un générateur afin de ne pas encombrer votre logique d'application principale. Par exemple:

def normalized(times):
    hms = False
    last_minute = 0
    for t in x:
        h, m, s = [int(i) for i in t.split(':')]
        if not hms:
            if h < last_minute:
                hms = True
            else:
                h, m, s = 0, h, m
                last_minute = m
        yield f'{h:02}:{m:02}:{s:02}'


x = ['59:55:00', '59:55:00', '59:58:00', '1:00:02', '1:00:05', '1:01:26']


for v in normalized(x):
    print(v)

Résulte en

00:59:55
00:59:55
00:59:58
01:00:02
01:00:05
01:01:26

Maintenant, dans la boucle, vous pouvez faire ce que vous voulez.

0
Chris Hunt 27 janv. 2019 à 02:12

Peut-être que strptime n'est pas le bon outil ici (une vérification d'erreur a été omise par souci de concision):

def convert(s):
    parts = [int(i) for i in s.split(":")]

    if parts[0] < 3:  # 3 is arbitrary value, may need adaption
        # Assuming format hour:min:sec
        h, m, s = parts
        millis = 0
    else:
        # Assuming format min:sec:millisec
        m, s, millis = parts
        h = 0

    return "1900-01-01 00:{:02}:{:02}".format(h * 60 + m, s)


x = ['59:55:00', '59:55:00', '59:58:00', '1:00:02', '1:00:05', '1:01:26']

print(*(convert(i) for i in x), sep="\n")

Production:

1900-01-01 00:59:55
1900-01-01 00:59:55
1900-01-01 00:59:58
1900-01-01 00:60:02
1900-01-01 00:60:05
1900-01-01 00:61:26
1
Michael Butscher 27 janv. 2019 à 02:03

Votre liste contient des durées plutôt que des heures. datetime.timedelta est conçu à cet effet, mais n'est pas nécessaire étant donné que vous voulez un format de chaîne très spécifique pour la sortie.

Le problème avec vos données d'entrée est l'incohérence du formatage. Si vous êtes prêt à coder en dur une valeur limite pour la première partie, vous pouvez appliquer une bascule via des instructions ternaires:

from datetime import timedelta

x = ['59:55:00', '59:55:00', '59:58:00', '1:00:02', '1:00:05', '1:01:26']

def converter(value, limit=59):
    var1, var2, var3 = map(int, value.split(':'))
    switch = var1 < limit
    mins = var1 * 60 + var2 if switch else var1
    secs = var3 if switch else var2
    return f'00:{mins:02}:{secs:02}'

res = list(map(converter, x))

print(res)
# ['00:59:55', '00:59:55', '00:59:58', '00:60:02', '00:60:05', '00:61:26']
1
jpp 27 janv. 2019 à 02:25
>>> time = datetime.datetime.now()
>>> halfformatted = time.strftime('00:{minutes}:%S.%f')
>>> minutes_total = time.hour * 60 + time.minute
>>> halfformatted.format(minutes=minutes_total)
'00:358:33.339341'
0
Alex Python 27 janv. 2019 à 02:01