0

I am trying to compare ISO DateTime with string datetime in Python code. I am getting datetime in JSON response from Azure Cloud which I need to compare to the last 24 hours before datetime. I am stuck at string-to-datetime conversion.

Here is the code

from datetime import datetime, timedelta

target_date = datetime.now() - timedelta (hours=24)
print(target_date.isoformat())
print(type(target_date))

createdOn = "2022-10-25T21:41:27.2824196Z"
post_time = datetime.strptime(createdOn, "%Y-%m-%dT%H:%M:%S.%f%z")
print(post_time)

I need to compare/check if createdOn is greater than target_date. While running the code, I am getting below error

    2023-08-07T13:22:11.914140
<class 'datetime.datetime'>
Traceback (most recent call last):
  File "/Users/Documents/GitHub/Mylabs/mytest.py", line 10, in <module>
    post_time = datetime.strptime(createdOn, "%Y-%m-%dT%H:%M:%S.%f%z")
  File "/Users/.pyenv/versions/3.8.17/lib/python3.8/_strptime.py", line 568, in _strptime_datetime
    tt, fraction, gmtoff_fraction = _strptime(data_string, format)
  File "/Users/.pyenv/versions/3.8.17/lib/python3.8/_strptime.py", line 349, in _strptime
    raise ValueError("time data %r does not match format %r" %
ValueError: time data '2022-10-25T21:41:27.2824196Z' does not match format '%Y-%m-%dT%H:%M:%S.%f%z'
K P
  • 3
  • 4
  • Does this answer your question? [How do I parse an ISO 8601-formatted date?](https://stackoverflow.com/questions/127803/how-do-i-parse-an-iso-8601-formatted-date) – sudden_appearance Aug 08 '23 at 20:35

2 Answers2

1

You might find it easier to use python-dateutil form PyPI to do the date parsing. This will parse the vast majority of known date formats and get things a little easier for you.

Once installed in PyPI, it can easily be used like so:

from datetime import datetime, timedelta, timezone

# Done by answerer for easier reference in code.
from dateutil.parser import parse as dateparse

target_date = datetime.now().astimezone(timezone.utc) - timedelta (hours=24)
print(target_date.isoformat())
print(type(target_date))

createdOn = "2022-10-25T21:41:27.2824196Z"
post_time = dateparse(createdOn)
print(post_time)

Effectively, it takes the headache of parsing manually out of the equation so that you know it will parse the datetime format properly and "just work" with varying formats of timestamps. While it doesn't solve your strptime issue it makes it easier to parse dates and timestamps. (This is just one of the many things that dateutil can do, but it does this very well)

Since dateutil's parser function returns a datetime object you can actually compare the two datetimes directly. However, you should make sure that your time for target_date is datetime.now.astimezone(timezone.utc) (which is why timezone is in the imports) to make sure you are comparing two timezone aware datetimes.

Then you can compare them directly.

print(target_date > post_time) for example will print a boolean value if target_date is later than or equal to post_time.


Python 3.11 and later have a fromisoformat mechanism for easier conversion, however if you are using anything earlier (like Python 3.8), using dateutil will be the superior parser method.

Thomas Ward
  • 2,714
  • 7
  • 36
  • 51
-3

The error you encountered is because the %z directive in the format string does not support the colon in the timezone offset. You can remove the colon from the timezone offset in your string, and use %f instead of %f%z to parse the fractional seconds separately. Here's the modified code:

from datetime import datetime, timedelta

target_date = datetime.now() - timedelta(hours=24)
print(target_date.isoformat())
print(type(target_date))

createdOn = "2022-10-25T21:41:27.2824196Z"
createdOn = createdOn[:-3] + createdOn[-2:]  # Remove colon from timezone offset
post_time = datetime.strptime(createdOn, "%Y-%m-%dT%H:%M:%S.%fZ")
print(post_time)

The createdOn string is modified by removing the colon from the timezone offset using string slicing. Then, the modified string is parsed using the format "%Y-%m-%dT%H:%M:%S.%fZ". The %Z specifier is used to match the "Z" character representing the timezone offset.

With these changes, the code should now be able to parse the createdOn string into a datetime object without raising any errors.

  • But it will make datetime object timezone naive, whereas the given datetime is timezone aware – sudden_appearance Aug 08 '23 at 20:39
  • I downvoted because: the problem is that `%f` cannot parse 7 digits of fractional seconds, not that `%z` cannot parse 'Z' to UTC ([docs](https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes)) - therefore, the explanation in the first paragraph is wrong. Second, the datetime string contains Z, specifying UTC. You should not ignore this; in general it is more safe to work with [aware](https://docs.python.org/3/library/datetime.html#aware-and-naive-objects) datetime here. – FObersteiner Aug 09 '23 at 05:14
  • 2
    @FObersteiner - This looks like another chatgpt answer (the other answer they published is 100% chatgpt) – David Makogon Aug 10 '23 at 20:07