0

I am looking for the fastest way to render a Python datetime object to an ISO8601 string. There are a few different methods for doing this out there, the native datetime module has strftime, isoformat and just plane old __str__. There are also many other more exotic methods, such as Pendulum (https://pendulum.eustace.io/), xml.utils.iso8601.tostring, and a few others here https://wiki.python.org/moin/WorkingWithTime

I am hoping there is something out there like for ciso8601, which has a great benchmark of comparing multiple methods here: https://github.com/closeio/ciso8601#benchmark

Stuart Buckingham
  • 1,574
  • 16
  • 25
  • 1
    Do you specifically need something faster than what you currently use, or is this purely out of interest? You already seem to have found multiple methods to do this; would it be sufficient for you to benchmark the ones you've found on your own? The question as it stands seems like it could be slightly off topic. – user10186512 Aug 12 '20 at 16:56
  • Sure, my question specifically is "What is the fastest method", as I am not aware of all of the possible methods of doing this, let alone which is the fastest. I am currently benchmarking the options I have above, and will post them when ready. – Stuart Buckingham Aug 12 '20 at 16:59
  • the `ciso8601` benchmark is incomplete to my opinion; the native `datetime.fromisoformat` outperforms it at least on my machine (Python 3.8.2 x64). See also: [A faster strptime?](https://stackoverflow.com/questions/13468126/a-faster-strptime). The other way round, `dtobj.isoformat()` outperforms `str(dtobj)` so I doubt you can get much more efficient. – FObersteiner Aug 12 '20 at 17:00

1 Answers1

0

I have benchmarked all the different methods I could find with the following results:

  • datetime.strftime - Time for 1000000 loops: 9.262935816994286
  • cast to string - Time for 1000000 loops: 4.381643378001172
  • datetime isoformat - Time for 1000000 loops: 4.331578577999608
  • pendulum to_iso8601_string - Time for 1000000 loops: 18.471532950992696
  • rfc3339 - Time for 1000000 loops: 24.731586036010412

The code to generate this is:

import timeit
from datetime import datetime
from pendulum import datetime as pendulum_datetime
from rfc3339 import rfc3339

dt = datetime(2011, 11, 4, 0, 5, 23, 283000)
pendulum_dt = pendulum_datetime(2011, 11, 4, 0, 5, 23, 283000)

repeats = 10**6

print('datetime strftime')
func1 = lambda: datetime.strftime(dt, "%Y-%m-%dT%H:%M:%S.%f%z")
print(func1())
print('Time for {0} loops: {1}'.format(
    repeats, timeit.timeit(func1, number=repeats))
    )

print('cast to string')
func2 = lambda: str(dt)
print(func2())
print('Time for {0} loops: {1}'.format(
    repeats, timeit.timeit(func2, number=repeats))
    )

print('datetime isoformat')
func3 = lambda: datetime.isoformat(dt)
print(func3())
print('Time for {0} loops: {1}'.format(
    repeats, timeit.timeit(func3, number=repeats))
    )

print('pendulum to_iso8601_string')
func4 = lambda: pendulum_dt.to_iso8601_string()
print(func4())
print('Time for {0} loops: {1}'.format(
    repeats, timeit.timeit(func4, number=repeats))
    )

print('rfc3339')
func5 = lambda: rfc3339(dt)
print(func5())
print('Time for {0} loops: {1}'.format(
    repeats, timeit.timeit(func5, number=repeats))
    )
FObersteiner
  • 22,500
  • 8
  • 42
  • 72
Stuart Buckingham
  • 1,574
  • 16
  • 25