ValueError: "time data %r does not match format %r"

194 views Asked by At

I'm trying to parse time using strptime:

t = datetime.strptime('2024-08-21T11:00:00 EDT', '%Y-%m-%dT%H:%M:%S %Z')

This code works for me in GMT+4, but it fails in GMT-9:

ValueError: time data '2024-08-21T11:00:00 EDT' does not match format '%Y-%m-%dT%H:%M:%S %Z'

What am I doing wrong?

2

There are 2 answers

1
LMC On BEST ANSWER

According to python docs strptime() only accepts certain values for %Z

strptime() only accepts certain values for %Z: any value in time.tzname for your machine’s locale the hard-coded values UTC and GMT

So someone living in Japan may have JST, UTC, and GMT as valid values, but probably not EST. It will raise ValueError for invalid values.

Testing locally

TZ="+4" python3 -c "import time; print(time.tzname)"
TZ="+4" python3 -c "import datetime; print(datetime.datetime.strptime('2024-08-21T11:00:00 EDT', '%Y-%m-%dT%H:%M:%S %Z'))"

Results

('', '')
ValueError: unconverted data remains: EDT

For a supported TZ

TZ="US/Eastern" python3 -c "import time; print(time.tzname)"
('EST', 'EDT')
TZ="US/Eastern" python3 -c "import datetime; print(datetime.datetime.strptime('2024-08-21T11:00:00 EDT', '%Y-%m-%dT%H:%M:%S %Z'))"
2024-08-21 11:00:00

Even error string changes for some TZ. America/Los_Angeles returns error as reported by OP.

 TZ="America/Los_Angeles" python3 -c "import datetime; print(datetime.datetime.strptime('2024-08-21T11:00:00 EDT', '%Y-%m-%dT%H:%M:%S %Z'))"

ValueError: time data '2024-08-21T11:00:00 EDT' does not match format '%Y-%m-%dT%H:%M:%S %Z'

Fails anyway even if tzname has values

TZ="America/Los_Angeles" python3 -c "import time; print(time.tzname)"
('PST', 'PDT')
0
Marcin Orlowski On

The problem is that timezone support (%Z) in Python's strptime() relies on the underlying C library, which varies between different systems and might not recognize certain timezone abbreviations like 'EDT'.

You can try to work that around by handling TZ separately. First parse the timestamp without TZ part, then manually adjust the result. Alternatively, use pytz or other libs that can have a broader and more up-to-date database of timezones.

from datetime import datetime, timedelta

def parse_datetime_with_tz(datetime_tz_str):
    # Split the input string into datetime and timezone parts
    datetime_str, tz_str = datetime_tz_str.rsplit(' ', 1)

    # Parse the datetime part
    dt = datetime.strptime(datetime_str, '%Y-%m-%dT%H:%M:%S')

    # TZ offests. Add more if needed 
    tz_offsets = {
        'EDT': -4,
    }

    tz_offset_hours = tz_offsets.get(tz_str, 0)
    tz_offset = timedelta(hours=tz_offset_hours)

    # Adjust the datetime for the timezone
    adjusted_dt = dt + tz_offset

    return adjusted_dt


timestamp = '2024-08-21T11:00:00 EDT'
parsed_dt = parse_datetime_with_tz(timestamp, timezone)
print(parsed_dt)