web-dev-qa-db-fra.com

Comment supprimer des données non converties d'un objet datetime Python

J'ai une base de données d'heures généralement correctes mais quelques-unes sont cassées comme ceci: Sat Dec 22 12:34:08 PST 20102015

Sans l'année invalide, cela fonctionnait pour moi:

end_date = soup('tr')[4].contents[1].renderContents()
end_date = time.strptime(end_date,"%a %b %d %H:%M:%S %Z %Y")
end_date = datetime.fromtimestamp(time.mktime(end_date))

Mais une fois que j'ai frappé un objet avec une année invalide, je reçois ValueError: unconverted data remains: 2, ce qui est génial mais je ne sais pas comment retirer au mieux les mauvais personnages de l'année. Ils vont de 2 à 6 unconverted characters.

Des pointeurs? Je voudrais juste trancher end_date mais j'espère qu'il existe une stratégie sûre pour les données.

25
Flowpoke

Ouais, je couperais les chiffres supplémentaires. En supposant qu'ils soient toujours ajoutés à la chaîne de données, alors quelque chose comme ça fonctionnerait:

end_date = end_date.split(" ")
end_date[-1] = end_date[-1][:4]
end_date = " ".join(end_date)

J'allais essayer d'obtenir le nombre de chiffres excédentaires de l'exception, mais sur mes versions installées de Python (2.6.6 et 3.1.2) cette information n'est pas réellement là; elle indique simplement que les données ne correspondent pas au format. Bien sûr, vous pouvez simplement continuer à supprimer les chiffres un par un et à effectuer une nouvelle analyse jusqu'à ce que vous n'obteniez pas d'exception.

Vous pouvez également écrire une expression régulière qui ne correspondra qu'à des dates valides, y compris le bon nombre de chiffres dans l'année, mais cela semble exagéré.

16
kindall

À moins que vous ne vouliez réécrire strptime (une très mauvaise idée), la seule vraie option que vous avez est de découper end_date et couper les caractères supplémentaires à la fin, en supposant que cela vous donnera le résultat correct que vous souhaitez.

Par exemple, vous pouvez intercepter ValueError, tranche et réessayer:

def parse_prefix(line, fmt):
    try:
        t = time.strptime(line, fmt)
    except ValueError as v:
        if len(v.args) > 0 and v.args[0].startswith('unconverted data remains: '):
            line = line[:-(len(v.args[0]) - 26)]
            t = time.strptime(line, fmt)
        else:
            raise
    return t

Par exemple:

parse_prefix(
    '2015-10-15 11:33:20.738 45162 INFO core.api.wsgi yadda yadda.',
    '%Y-%m-%d %H:%M:%S'
) # -> time.struct_time(tm_year=2015, tm_mon=10, tm_mday=15, tm_hour=11, tm_min=33, ...
15
Adam Rosenfield

Amélioration (j'espère) du code d'Adam Rosenfield:

import time

for end_date in ( 'Fri Feb 18 20:41:47 Paris, Madrid 2011',
                  'Fri Feb 18 20:41:47 Paris, Madrid 20112015'):

    print end_date

    fmt = "%a %b %d %H:%M:%S %Z %Y"
    try:
        end_date = time.strptime(end_date, fmt)
    except ValueError, v:
        ulr = len(v.args[0].partition('unconverted data remains: ')[2])
        if ulr:
            end_date = time.strptime(end_date[:-ulr], fmt)
        else:
            raise v

    print end_date,'\n'
5
eyquem

Voici une doublure encore plus simple que j'utilise:

end_date = end_date[:-4]

1
skeller88

strptime() s'attend vraiment à voir une date correctement formatée, donc vous devrez probablement faire un munging sur le end_date chaîne avant de l'appeler.

C'est une façon de couper le dernier élément du end_date à 4 caractères:

chop = len(end_date.split()[-1]) - 4
end_date = end_date[:-chop]
0
payne