#python #json #datetime #parsing
#python #json #datetime #синтаксический анализ
Вопрос:
я пытаюсь проанализировать строки времени из файла json, сохранить только те строки, которые могут быть проанализированы с использованием стандарта ISO datetime с помощью strptime, принять значения createdAt, которые уже есть в стандарте ISO datetime, и преобразовать их обратно в строки (в часовом поясе UTC) с помощью strftime .
вот как выглядят мои данные json, где createdAt для четвертого заголовка уже находится в стандарте ISO datetime, но пятый заголовок должен быть удален, поскольку 12345678 является недопустимым объектом времени.
{"title_text": "Fourth title", "createdAt": "2020-10-17T02:56:51 07:00", "text": "Some post content", "author": "cereal"}
{"title_text": "Fifth title", "createdAt": "12345678", "text": "Some post content", "author": "ninja"}
и это два фрагмента кода, с которыми я работал.
datetime_formats = ("%Y-%m-%dT%H:%M:%S%z", "%Y-%m-%dT%H:%M:%S%Z")
for time in range(len(data)):
for format in datetime_formats:
try:
data[time]['createdAt'] = datetime.strptime(str(time), format).replace(tzinfo=pytz.UTC)
except ValueError:
pass
else:
break
else:
data.remove(time)
^ этот фрагмент кода выдает мне ошибку ValueError: list.remove(x): x отсутствует в списке
def parse_createdAt_time(output_format="%Y-%m-%dT%H:%M:%S%Z"):
datetime_formats = ("%Y-%m-%dT%H:%M:%S%z", "%Y-%m-%dT%H:%M:%S%Z")
for time in data[1]['createdAt']:
for format in datetime_formats:
try:
time = datetime.strptime(time, format).replace(tzinfo=datetime.timezone.utc)
return time.strftime(output_format)
except ValueError:
pass
else:
break
else:
data.remove(time)
^ я попытался использовать немного другой подход к этому коду и попытался модулировать его, но он даже не проанализировал мой ввод json. он просто выплевывает мои данные json, нетронутые (включая запись 12345678 выше)
мне также разрешено использовать только модуль datetime, но я потратил на это слишком много времени и до сих пор не совсем понимаю, что не так.
текущий код (inspo от @MrFuppes), который выдает четыре «ошибки» и ошибку типа: объект ‘datetime.datetime’ не поддается подписке. кажется, что все временные строки json, которые используют стандарт iso datetime, анализируются как ошибка значения, а «пятый заголовок» (который является недопустимым форматом времени) выдает мне ошибку типа.
def datetime_valid(data, output_format="%Y-%m-%dT%H:%M:%S%Z"):
final_json = []
for line in data:
for format in ("%Y-%m-%dT%H:%M:%S%z", "%Y-%m-%dT%H:%M:%S%Z"):
try: # see if json string is in iso datetime standard
check_iso = datetime.strptime(str(line['createdAt']), format)
except ValueError:
print("error")
else: # if string is in iso format, convert to utc and append to final_json array
line = check_iso.astimezone(timezone.utc).replace(tzinfo=None)
final_json.append(line.strftime(output_format))
return final_json
Комментарии:
1. примечание: не изменяйте итерацию во время итерации по ней (например
data.remove(time)
) — это может привести к довольно запутанным результатам 😉
Ответ №1:
если у вас есть дата / время в строке изоформата, почему вы не используете методы изоформата? все они являются частью стандартной библиотеки…
from datetime import datetime, timezone
l = [{"title_text": "Fourth title", "createdAt": "2020-10-17T02:56:51 07:00", "text": "Some post content", "author": "cereal"},
{"title_text": "Fifth title", "createdAt": "12345678", "text": "Some post content", "author": "ninja"}]
out = []
for d in l:
try:
dt = datetime.fromisoformat(d['createdAt'])
except ValueError:
pass
else:
d['createdAt'] = dt.astimezone(timezone.utc).isoformat()
out.append(d)
# out
# [{'title_text': 'Fourth title',
# 'createdAt': '2020-10-16T19:56:51 00:00',
# 'text': 'Some post content',
# 'author': 'cereal'}]
Комментарии:
1. это работает, когда я копирую и вставляю его в ячейку jupyter, но не тогда, когда я меняю l на свой фактический файл json:/ я внес изменения в ваш код (например, все еще придерживаюсь strptime, потому что я не хочу потерять информацию в%H:%M:%S%Z)но в итоге я получаю «ошибку» (x4) и ошибку типа: объект ‘datetime.datetime’ не подлежит подписке. я отредактировал свой пост, чтобы включить этот код более подробную информацию о том, что, по моему мнению, может произойти, не могли бы вы взглянуть?
Ответ №2:
Я не уверен, что точно понимаю вашу цель, но предполагая, что вы просто хотите отфильтровать свой список данных от записей с неправильным форматом даты для createdAt, вы можете использовать функцию для создания нового списка только с допустимыми записями :
from datetime import datetime
import pytz
raw_data = [
{"title_text": "Fourth title", "createdAt": "2020-10-17T02:56:51 07:00", "text": "Some post content", "author": "cereal"},
{"title_text": "Fifth title", "createdAt": "12345678", "text": "Some post content", "author": "ninja"}
]
datetime_formats = ("%Y-%m-%dT%H:%M:%S%z", "%Y-%m-%dT%H:%M:%S%Z")
def filter_data(data):
out = []
for d in data:
for date_format in datetime_formats:
try:
date = datetime.strptime(d['createdAt'], date_format)
d['createdAt'] = date.strftime(datetime_formats[0])
out.append(d)
break
except ValueError:
pass
return out
выдает
[{'title_text': 'Fourth title',
'createdAt': '2020-10-17T02:56:51 0700',
'text': 'Some post content',
'author': 'cereal'}]