Splitting string by colon in Python

Viewed 822

I have a reminder app and I need to split the time like 3:30 a.m.. I used re module but I failed.

What I'm trying to do is split the time by colon in front of the words in list. But list has multiple words. Like a.m., am

The program should try the words until it gets the right match, and split the time by colon, such as hour and minute. 13:25 to [13, 25].

Here is an example:

import re

am = ['a.m.', 'am', 'ante meridiem']
timeinp = 'reminder for 3:30 am'

for a in am:
    gettime = re.search(fr'\b\d?\d:\d\d\b {a}', timeinp).group(0)
    gettime = re.split('[:]', gettime)
    print(gettime)

This code gives me AttributeError: 'NoneType' object has no attribute 'group'.

2 Answers

You may use a single regex with capturing groups to instantly get access to hours and minutes if there is a match:

import re

am = ['a.m.', 'am', 'ante meridiem']
timeinp = 'reminder for 3:30 am'

a = "|".join(map(re.escape, am))
gettime = re.search(fr'\b(\d{{1,2}}):(\d{{2}})\s*(?:{a})', timeinp)
if gettime:
    print(list(map(int, gettime.groups()))) # => [3, 30]
else:
    print("no match")

See Python demo

Note that gettime.groups() contains a tuple containing all the subgroups of the match, from 1 up to however many groups are in the pattern. The capturing groups are all those parts of the pattern enclosed with (...).

You need to re.escape your am list items, otherwise, . matches any char. You need to use \. outside a character class to match a literal dot.

As others have noted, you're getting an AttributeError due to re.search() returning None in cases where an item stored in am results in no match within your loop.

The below example is similar to others in handling cases in which re.search() returns None, however it:

  • Uses a lookahead to in the pattern as to not include the am item in the match returned.
  • Further processes the match into a list of 2 int instances instead of str instances.
  • Breaks the loop following print(gettime) to stop any further iterations and keep the list value assigned to gettime available following loop execution.
  • Includes some basic logic to printout a No time match found! message for cases in which the loop exits without matching as per your criteria.
import re

am = ['a.m.', 'am', 'ante meridiem']
timeinp = 'reminder for 3:30 am'
gettime = None

for a in am:
     gettime = re.search(fr'\b\d?\d:\d\d\b(?= {a})', timeinp)
     if gettime:
            gettime = [ int(i) for i in re.split(':', gettime.group()) ]
            print(gettime)
            break
            
if not gettime:
    print('No time match found!')
Related