Как удалить неконвертированные данные из объекта datetime Python

у меня есть база данных в основном правильных дат, но некоторые из них сломаны так:Sat Dec 22 12:34:08 PST 20102015

без инвалидного года это работало для меня:

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))

но как только я попал в объект с недействительным годом, я получаю ValueError: unconverted data remains: 2, что здорово, но я не уверен, как лучше всего удалить плохие персонажи из года. Они варьируются от 2 до 6 unconverted characters.

какие-нибудь советы? Я бы просто нарезал end_date но я надеюсь, что есть стратегия datetime-safe.

5 ответов


Да, я бы просто отрубил лишние числа. Предполагая, что они всегда добавляются к datestring, тогда что-то вроде этого будет работать:

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

Я собирался попытаться получить количество избыточных цифр из исключения, но на моих установленных версиях Python (2.6.6 и 3.1.2) эта информация на самом деле не существует; он просто говорит, что данные не соответствуют формату. Конечно, вы можете просто продолжать отсекать цифры по одному за раз и повторно анализировать, пока не получите исключение.

вы также можете написать регулярное выражение, которое будет соответствовать только действительным датам, включая правильное количество цифр в году, но это кажется излишним.


если вы не хотите переписать strptime (очень плохая идея), единственный реальный вариант у вас есть, чтобы нарезать end_date и обрубить лишние символы в конце, предполагая, что это даст вам правильный результат вы намереваетесь.

например, вы можете поймать ValueError, нарежьте и повторите попытку:

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

например:

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, ...

улучшение (я надеюсь) кода Адама Розенфилда:

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'

strptime() действительно ожидает увидеть правильно отформатированную дату, поэтому вам, вероятно, нужно сделать некоторые munging на end_date строка перед вызовом.

Это один из способов нарезать последний пункт в end_date до 4 символов:

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

вот еще более простой однострочный я использую:

end_date = end_date[:-4]