0

I've read previous Stack questions but I am coming unstuck with a datetime. My code looks like this and each time raises and error on just some of the transactions.

       # r.createdAt = datetime.strptime(unparsed_review['createdAt'], '%Y-%m-%dT%H:%M:%S.%fZ') # ValueError: time data '2020-11-25T14:54:00Z' does not match format '%Y-%m-%dT%H:%M:%S.%fZ'
       # r.createdAt = datetime.strptime(unparsed_review['createdAt'], '%Y-%m-%dT%H:%M:%SZ')  # ValueError: time data '2023-03-06T11:28:22.746919Z' does not match format '%Y-%m-%dT%H:%M:%SZ'
       # r.createdAt = datetime.strptime(unparsed_review['createdAt'], '%Y-%m-%dT%H:%M:%S%z')  # ValueError: time data '2023-03-06T11:28:22.746919Z' does not match format '%Y-%m-%dT%H:%M:%S%z'

Currently I am successfully over coming it like this which is brutal but does work.. I'm not sure what the final piece of the string is or if it's changing.

    if not processed:
        try:
            r.createdAt = datetime.strptime(unparsed_review['createdAt'], '%Y-%m-%dT%H:%M:%S.%fZ')
            processed = True
        except:
            processed = False

    if not processed:
        try:
            r.createdAt = datetime.strptime(unparsed_review['createdAt'], '%Y-%m-%dT%H:%M:%SZ')
            processed = True
        except:
            processed = False

    if not processed:
        try:
            r.createdAt = datetime.strptime(unparsed_review['createdAt'], '%Y-%m-%dT%H:%M:%S%z')
            processed = True
        except:
            processed = False
Johnny John Boy
  • 3,009
  • 5
  • 26
  • 50
  • What does `unparsed_review['createdAt']` look like, does it change? If you don't know the exact format, out of several possible, why not just use loop? – buran Mar 14 '23 at 14:36
  • Does this answer your question? [How to format date string via multiple formats in python](https://stackoverflow.com/questions/23581128/how-to-format-date-string-via-multiple-formats-in-python) – buran Mar 14 '23 at 14:40

2 Answers2

2

The general approach of trying different formats until one works seems fine, but I'd suggest using a loop instead of copy+pasting the logic:

for fmt in (
    '%Y-%m-%dT%H:%M:%S.%fZ',
    '%Y-%m-%dT%H:%M:%SZ',
    '%Y-%m-%dT%H:%M:%S%z',
):
    try:
        r.createdAt = datetime.strptime(unparsed_review['createdAt'], fmt)
        break
    except ValueError:
        continue
else:
    raise ValueError(f"No formats matched {unparsed_review['createdAt']}")

# r.createdAt now guaranteed to have been set successfully
Samwise
  • 68,105
  • 3
  • 30
  • 44
  • you're missing `'%Y-%m-%dT%H:%M:%S.%f%z'` - also, it is important to note that there is a difference between 'Z' and '%z' . One gives naive datetime, the other gives aware datetime. – FObersteiner Mar 14 '23 at 16:21
0

You could try dateutil.parser.parse, it takes a wider variety of date formats.

from dateutil.parser import parse
try:
    r.createdAt = parse(unparsed_review['createdAt'])
    processed = True
except ValueError:
    print("oops, couldn't parse this:", unparsed_review['createdAt'])
    processed = False

Best of luck.

Brock Brown
  • 956
  • 5
  • 11