1

I have a str that I want to convert to a datetime. This str is this: 'Thursday, September 9, 2021 at 11:50 AM CDT. I am using the datetime.strptime() function, but it seems like the AM or time zone is not being recognized.

When I use the code

time = 'Thursday, September 9, 2021 at 11:50 AM CDT'
time = datetime.strptime(time, '%A, %B %d, %Y at %I:%M %p %Z')

I get the following: ValueError: time data 'Thursday, September 9, 2021 at 11:50 AM CDT' does not match format '%A, %B %d, %Y at %I:%M %p %Z:%M %p %Z'

I've been able to convert the first part up until the %p %Z part, at which I get the following error:

ValueError: time data 'AM CDT' does not match format '%p %Z'

Any ideas on how dt.strptime() can recognize AM/PM and the time zone correctly?

cjw528
  • 41
  • 3
  • 1
    Does this answer your question? [Python strptime() and timezones?](https://stackoverflow.com/questions/3305413/python-strptime-and-timezones) – FObersteiner Nov 04 '21 at 14:44

1 Answers1

1

Not sure of the best approach, but since Python 3.9 you can use the ZoneInfo module for this:

from datetime import datetime
from zoneinfo import ZoneInfo


CDT = ZoneInfo('CST6CDT')
# or alternatively:
# CDT = ZoneInfo('US/Central')

time = 'Thursday, September 9, 2021 at 1:50 PM'
time = datetime.strptime(time, '%A, %B %d, %Y at %I:%M %p')
time = time.replace(tzinfo=CDT)

print(time)  # 2021-09-09 13:50:00-05:00

@MrFuppes made a good point about an ambiguity between the CST6EDT and US/Central zones. However, when I tried a quick test in DST and outside of DST, I couldn't see any noticeable difference, as the time zone seemed to adjust automatically - which indicates that either of those zone values appear to be DST- aware (unless I'm missing something of course).

I added an example below:

from datetime import datetime
from zoneinfo import ZoneInfo


# CDT = ZoneInfo('CST6CDT')
CDT = ZoneInfo('US/Central')

# Note: DST in 2021, ends on November 7th
time_dst = 'Saturday, November 6, 2021 at 1:50 PM'
time_st = 'Monday, November 8, 2021 at 1:50 PM'

time_dst = datetime.strptime(time_dst, '%A, %B %d, %Y at %I:%M %p')
time_dst = time_dst.replace(tzinfo=CDT)
time_st = datetime.strptime(time_st, '%A, %B %d, %Y at %I:%M %p')
time_st = time_st.replace(tzinfo=CDT)

print('DST: ', time_dst)
print('ST:  ', time_st)

Output appears to be the same despite which ZoneInfo object is used:

DST:  2021-11-06 13:50:00-05:00
ST:   2021-11-08 13:50:00-06:00
rv.kvetch
  • 9,940
  • 3
  • 24
  • 53
  • I think you actually want a time zone like US/Central – FObersteiner Nov 04 '21 at 14:45
  • I actually couldn't find any info on that. Is there any difference between US/Central and CST6CDT? – rv.kvetch Nov 04 '21 at 14:46
  • 1
    This is a start, but I actually have a series of observations (all strings) with the date above. The timezone is constantly changing like the other times. Currently looking into timezone though about UTC codes. Thanks! – cjw528 Nov 04 '21 at 14:52
  • 1
    Yes I think it's just a constant offset of 6 hours, see https://github.com/eggert/tz/blob/8b409e22d7e1b70bf9364b014a8e359908a507a9/northamerica#L204 - a US Central time zone would have DST, so UTC +6/+5 – FObersteiner Nov 04 '21 at 15:05
  • @MrFuppes I tried to test with the US/Central zone as suggested, but I didn't find any noticeable difference in output between CST6CDT, which further adds to the ambiguity I suppose. I updated my answer above if you're interested. – rv.kvetch Nov 04 '21 at 16:03
  • 1
    If the OP has multiple time zone abbreviations to parse, I think the dateutil approach (tzinfos mapping dict) is a nice way, see the dupe I linked. I think I also wrote an answer using a similar technique + zoneinfo somewhere on SO ;-) – FObersteiner Nov 04 '21 at 17:48