【问题标题】:A faster strptime?更快的strptime?
【发布时间】:2012-11-08 05:17:30
【问题描述】:

我的代码以“YYYY-MM-DD”格式读取大量日期。解析所有这些日期,以便它可以添加一天、两天或三天,然后以相同的格式写回,这会大大减慢速度。

 3214657   14.330    0.000  103.698    0.000 trade.py:56(effective)
 3218418   34.757    0.000   66.155    0.000 _strptime.py:295(_strptime)

 day = datetime.datetime.strptime(endofdaydate, "%Y-%m-%d").date()

有什么建议可以加快一点(或很多)吗?

【问题讨论】:

    标签: python performance datetime strptime


    【解决方案1】:

    因子 7 足够吗?

    datetime.datetime.strptime(a, '%Y-%m-%d').date()       # 8.87us
    
    datetime.date(*map(int, a.split('-')))                 # 1.28us
    

    编辑:显式切片的好主意:

    datetime.date(int(a[:4]), int(a[5:7]), int(a[8:10]))   # 1.06us
    

    这使得因子 8。

    【讨论】:

    • 在上下文中:strptime = 128s,this = 61s,对于 55s 是明确的:datetime.date(int(a[:4]), int(a[5:7]), int(a[8:10]))。现在替换 strftime 并可能修剪另外 10 秒...谢谢。
    【解决方案2】:

    Python 3.7+:fromisoformat()

    从 Python 3.7 开始,datetime 类有一个方法 fromisoformat。需要注意的是,这也可以应用于这个问题:

    性能与strptime()

    与普通strptime 相比,显式字符串切片可能使您的性能提高约9 倍,但使用内置fromisoformat 方法您可以获得约90 倍的性能提升!

    %timeit isofmt(datelist)
    569 µs ± 8.45 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    
    %timeit slice2int(datelist)
    5.51 ms ± 48.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
    
    %timeit normalstrptime(datelist)
    52.1 ms ± 1.27 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
    
    from datetime import datetime, timedelta
    base, n = datetime(2000, 1, 1, 1, 2, 3, 420001), 10000
    datelist = [(base + timedelta(days=i)).strftime('%Y-%m-%d') for i in range(n)]
    
    def isofmt(l):
        return list(map(datetime.fromisoformat, l))
        
    def slice2int(l):   
        def slicer(t):
            return datetime(int(t[:4]), int(t[5:7]), int(t[8:10]))
        return list(map(slicer, l))
    
    def normalstrptime(l):
        return [datetime.strptime(t, '%Y-%m-%d') for t in l]
        
    print(isofmt(datelist[0:1]))
    print(slice2int(datelist[0:1]))
    print(normalstrptime(datelist[0:1]))
    
    # [datetime.datetime(2000, 1, 1, 0, 0)]
    # [datetime.datetime(2000, 1, 1, 0, 0)]
    # [datetime.datetime(2000, 1, 1, 0, 0)]
    

    Python 3.8.3rc1 x64 / Win10

    【讨论】:

    • 但是 fromisoformat 是“这不支持解析任意 ISO 8601 字符串 - 它仅用作 datetime.isoformat() 的逆运算”来自docs.python.org/3/library/… 所以日期如“2020-08-24T00 :00:00.00+00:00" 不起作用
    • @visch 好吧,如果你问我(我们现在有 3.10!)。 但是为什么这会阻止您充分利用现有的功能呢?
    • 我很想使用该功能,但我遇到了至少一个不起作用的情况(最后一条评论中的那个)(即使我很确定它是有效的 iso 8601约会时间)。我最终选择了github.com/closeio/ciso8601
    • @visch 这是一个不错的选择。我想我做了一次基准测试,而 fromisoformat(如果有效)只是稍微快一点。
    【解决方案3】:

    对于 ISO 格式的无时区字符串,例如:"2021-01-04T14:30:03.123"

    datetime.datetime(int(d[:4]), int(d[5:7]), int(d[8:10]), int(d[11:13]), int(d[14:16]), int(d[17:19]), int(d[20:]))
    

    似乎比strptime()fromisoformat() 运行得更快。

    【讨论】:

      猜你喜欢
      • 2010-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-16
      • 1970-01-01
      • 2016-10-20
      • 2015-11-13
      • 1970-01-01
      相关资源
      最近更新 更多