1

I want to convert strings such as "2023-08-04T13:33:33.614Z" or "2023-05-06T05:55:00Z" to datetime object. Some strings have decimal digits in seconds (e.g. 2023-08-04T13:33:33 .614 Z) and some strings have not (e.g. 2023-05-06T05:55:00Z) raising error "time data %r does not match format"

How to solve it?

Full problem:

I'm trying to filter some data from dictionaries:

from datetime import datetime

def filter_by_time(dictionary_list, start_date, end_date):
    filtered_list = []
    for entry in dictionary_list:
        time_str = entry['time']
        entry_time = datetime.strptime(time_str, '%Y-%m-%dT%H:%M:%S.%fZ')
        if start_date <= entry_time <= end_date:
            filtered_list.append(entry)
    return filtered_list

# Example list of dictionaries
data = [
    {'name': 'Ana', 'city': 'New York', 'time': '2023-08-04T13:33:33.614Z'},
    {'name': 'John', 'city': 'Los Angeles', 'time': '2023-05-12T16:53:20.349Z'},
    {'name': 'Barney', 'city': 'Miami', 'time': '2023-05-09T16:49:20.752Z'},
    {'name': 'Gabriel', 'city': 'Seattle', 'time': '2023-05-06T05:55:00Z'}
]

# Get user input for start_date and end_date
start_date_input = input("Enter the start date (YYYY-MM-DD): ")
end_date_input = input("Enter the end date (YYYY-MM-DD): ")

start_date = datetime.strptime(start_date_input, '%Y-%m-%d')
end_date = datetime.strptime(end_date_input, '%Y-%m-%d')

filtered_data = filter_by_time(data, start_date, end_date)

print("Filtered data:")
for entry in filtered_data:
    print(entry)

When I try to filter values from 2023-05-01 to 2023-05-10, I got the following error:

raise ValueError("time data %r does not match format %r" %
ValueError: time data '2023-05-06T05:55:00Z' does not match format '%Y-%m-%dT%H:%M:%S.%fZ'

I noticed if I convert all my entries to three decimal digits in the seconds (e.g '2023-05-06T05:55:00Z' -> '2023-05-06T05:55:00.000Z', the error disappears.

How to filter my entries?

anjosdev
  • 11
  • 2
  • `%Y-%m-%dT%H:%M:%SZ` is the format you should use if the dates have no subsecond value. – Niloct Aug 21 '23 at 02:10
  • I usually have subsecond values for my entries and ideally I would like to keep them. However they aren't useful, so I think the best approach will be to ignore the subseconds and follow your suggestion. – anjosdev Aug 21 '23 at 02:23
  • 1
    You can simplify this question to a list of time strings in the different formats that you are trying to parse. Then parse those strings with a single format string to show the error. All of the rest of your code is just extra details that get in the way of your actual question. – Code-Apprentice Aug 21 '23 at 02:32
  • 1
    if you're only dealing with variants of ISO8601 compatible formats, you can use [datetime.fromisoformat](https://docs.python.org/3/library/datetime.html#datetime.datetime.fromisoformat) - but note that with Python < 3.11, you'll need to replace 'Z' with '+00:00', see [here](https://stackoverflow.com/a/62769371/10197418). – FObersteiner Aug 21 '23 at 06:30

1 Answers1

0

It will work even if you make time string in that way:

{'name': 'Gabriel', 'city': 'Seattle', 'time': '2023-05-06T05:55:0.0Z'}

Why you need to make it in that way?

Because when in template you write %S.%fZ - you assume 2 numbers. For seconds and milliseconds and sign of '.' between them with symbol 'Z' at the end. So Python waits these 2 numbers as you declaired it in temlpate.