【问题标题】:parsing string from json to datetime object将字符串从 json 解析为 datetime 对象
【发布时间】:2020-10-23 15:56:46
【问题描述】:

我正在尝试从 json 文件中解析时间字符串,只保留可以使用带有 strptime 的 ISO 日期时间标准解析的行,获取已经在 ISO 日期时间标准中的 createdAt 值并将它们转换回字符串(在UTC 时区)和 strftime。

这就是我的 json 数据的样子,其中第四个标题的 createdAt 已经符合 ISO 日期时间标准,但第五个标题应该被删除,因为 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"}

这是我一直在使用的两个代码 sn-ps。

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)

^ 这段代码 sn-p 给了我一个 ValueError: list.remove(x): x not in list

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 模块,但我在这方面花了太多时间,仍然不太清楚哪里出了问题。

当前代码(来自@MrFuppes 的inspo),它给出了四个“错误”和一个TypeError:'datetime.datetime' 对象不可下标。似乎所有使用 iso 日期时间标准的 json 时间字符串都被解析为值错误,并且“第五个标题”(这是一种无效的时间格式)给了我类型错误。

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

【问题讨论】:

  • 旁注:在迭代时不要修改可迭代对象(例如data.remove(time))——这会导致非常混乱的结果;-)

标签: python json datetime parsing


【解决方案1】:

如果isoformat 字符串中有日期/时间,为什么不使用isoformat 方法?它们都是标准库的一部分...

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'}] 

【讨论】:

  • 这在我将其复制并粘贴到 jupyter 单元格时有效,但当我用我的实际 json 文件更改 l 时无效:/ 我对您的代码进行了修改(例如,仍然坚持使用 strptime,因为我不想丢失 %H:%M:%S%Z) 中的信息,但我最终会出现“错误”(x4)并且 TypeError: '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'}]

【讨论】:

    猜你喜欢
    • 2014-01-17
    • 2013-04-04
    • 2013-03-12
    • 1970-01-01
    • 2019-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多