Как удалить неконвертированные данные из объекта datetime в Python
У меня есть база данных с в основном правильными датами и временами, но несколько записей повреждены, например: <code>Sat Dec 22 12:34:08 PST 20102015</code>
.
Без неверного года код работал для меня следующим образом:
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))
Но когда я сталкиваюсь с объектом с неверным годом, я получаю ошибку <code>ValueError: unconverted data remains: 2</code>
. Это полезно, но я не уверен, как лучше всего удалить неправильные символы из года. Они могут варьироваться от 2 до 6 <code>неконвертированных символов</code>
.
Можете дать несколько советов? Я бы мог просто обрезать <code>end_date</code>
, но надеюсь найти безопасную для datetime стратегию.
5 ответ(ов)
Если вы не хотите переписывать функцию 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, ...
Да, я бы просто отрезал лишние цифры. Предполагая, что они всегда добавляются к строке даты, то нечто подобное сработает:
end_date = end_date.split(" ")
end_date[-1] = end_date[-1][:4]
end_date = " ".join(end_date)
Я собирался попробовать получить количество лишних цифр из исключения, но в установленных у меня версиях Python (2.6.6 и 3.1.2) этой информации на самом деле нет; просто написано, что данные не соответствуют формату. Конечно, вы можете продолжать поочередно отрезать цифры и повторно разбирать строку, пока не получите исключение.
Вы также можете написать регулярное выражение, которое будет соответствовать только допустимым датам, включая правильное количество цифр в годе, но это кажется излишним.
Вот еще один простой однострочник, который я использую:
end_date = end_date[:-4]
Этот код обрезает последние четыре символа строки end_date
.
Ваш код содержит несколько моментов, которые можно улучшить для повышения его читаемости и надежности. Я также рекомендую использовать более современный синтаксис Python и улучшить обработку исключений. Ниже приведён переработанный вариант вашего кода:
import time
def parse_end_dates(end_dates):
fmt = "%a %b %d %H:%M:%S %Z %Y"
for end_date in end_dates:
print(end_date)
try:
parsed_date = time.strptime(end_date, fmt)
except ValueError as e:
unconverted_data_length = len(e.args[0].partition('unconverted data remains: ')[2])
if unconverted_data_length:
parsed_date = time.strptime(end_date[:-unconverted_data_length], fmt)
else:
raise
print(parsed_date, '\n')
end_dates = [
'Fri Feb 18 20:41:47 Paris, Madrid 2011',
'Fri Feb 18 20:41:47 Paris, Madrid 20112015'
]
parse_end_dates(end_dates)
Основные изменения:
- Функция: Я обернул основной код в функцию
parse_end_dates
, что делает его более организованным и повторно используемым. - Печать: Обновил синтаксис
print
, чтобы он соответствовал Python 3 (если вы используете более ранние версии, вернитесь к старому стилю печати). - Обработка исключений: Изменил синтаксис обработки исключений с
except ValueError, v:
наexcept ValueError as e:
. Это более современный и понятный способ. - Чтение переменной: Переименовал переменные для большей читаемости, например,
v
наe
иulr
наunconverted_data_length
.
Теперь ваш код стал более понятным и соответствует современным стандартам Python.
Функция strptime()
действительно ожидает правильно отформатированную дату, поэтому вам, вероятно, нужно немного обработать строку end_date
перед ее вызовом.
Вот один из способов убрать последние символы в end_date
, оставив только 4 символа в конце:
chop = len(end_date.split()[-1]) - 4
end_date = end_date[:-chop]
Обратите внимание, что данный код предполагает, что в конце строки end_date
находится элемент, у которого длина больше 4 символов. Убедитесь, что ваша строка соответствует этому условию, чтобы избежать возможных ошибок.
Как разобрать часовой пояс с двоеточием
Как преобразовать datetime в date?
Как конвертировать секунды в часы, минуты и секунды?
Как рассчитать количество дней между двумя заданными датами
Преобразование строки даты JSON в datetime в Python