2

I am trying to parse and convert "2020-07-30T20:40:33.1000000Z"in Python:

from datetime import datetime

Data = [{'id': 'XXXXXXXXXXXXX', 'number': 3, 'externalId': '0000', 'dateCreated': '2020-07-30T20:40:33.1005865Z', 'dateUpdated': '2020-07-30T20:40:33.36Z'}], 'tags': []}]
for i in Data:
        creationtime= datetime.strptime(i["dateCreated"],"%Y-%m-%dT%H:%M:%S")

Error:

    raise ValueError("unconverted data remains: %s" %
ValueError: unconverted data remains: .1005865Z

I tried :

%Y-%m-%dT%H:%M:%S.%fZ

Can anyone please suggest the correct format that I am missing.

1 Answers1

3

Python 3.11 update

This is now handled correctly by the ISO format parser. Ex:

Python 3.11.4 (main, Jun 27 2023, 19:27:25) [GCC 13.1.1 20230614 (Red Hat 13.1.1-4)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from datetime import datetime
>>> s = "2020-07-30T20:40:33.1000000Z"
>>> dt = datetime.fromisoformat(s)
>>> print(dt)
2020-07-30 20:40:33.100000+00:00

Old answer

If you really have 7 decimal places of fractional seconds and don't care about the 1/10th of the microseconds, you could use a re.sub and datetime.fromisoformat:

import re
from datetime import datetime 

s = "2020-07-30T20:40:33.1000000Z"
dt = datetime.fromisoformat(re.sub('[0-9]Z', '+00:00', s))

print(dt)
print(repr(dt))
2020-07-30 20:40:33.100000+00:00
datetime.datetime(2020, 7, 30, 20, 40, 33, 100000, tzinfo=datetime.timezone.utc)

...or use dateutil's parser:

from dateutil import parser
dt = parser.parse(s)

print(dt)
print(repr(dt))
2020-07-30 20:40:33.100000+00:00
datetime.datetime(2020, 7, 30, 20, 40, 33, 100000, tzinfo=tzutc())

...or even pandas's to_datetime, if you maybe work with that lib anyway:

import pandas as pd
dt = pd.to_datetime(s)

print(dt)
print(repr(dt))
2020-07-30 20:40:33.100000+00:00
Timestamp('2020-07-30 20:40:33.100000+0000', tz='UTC')

often irrelevant (depending on use-case) but note that convenience costs you some more time:

%timeit datetime.fromisoformat(re.sub('[0-9]Z', '+00:00', s))
1.92 µs ± 151 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

%timeit parser.parse(s)
79.8 µs ± 3.46 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

%timeit pd.to_datetime(s)
62.4 µs ± 1.17 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
FObersteiner
  • 22,500
  • 8
  • 42
  • 72
  • Thanks for answer MrFuppes, how can I convert it to `%m/%d/%Y %H:%M:%S` after `datetime.fromisoformat(re.sub('[0-9]Z', '+00:00', case["dateCreated"])` – Ashish Bansal Aug 17 '20 at 09:22
  • @AshishBansal: just append `.strftime('%m/%d/%Y %H:%M:%S')` to the line of code – FObersteiner Aug 17 '20 at 09:23
  • I tried the same way and I am comparing it with other date but it is giving me error `TypeError: '>' not supported between instances of 'str' and 'datetime.datetime'` I am using this condition: `if creationtime>lastruntime:` – Ashish Bansal Aug 17 '20 at 09:28
  • @AshishBansal: you can only compare str with str or datetime with datetime. don't mix it up, that's what the error says. I suggest to compare datetime against datetime - which probably means that you shouldn't cast to str using `strftime`. – FObersteiner Aug 17 '20 at 09:31