Exercise 2 solution import re def parse_time(t): m = re.fullmatch(r"(?P\d{1,2}):(?P\d{2})(?::(?P\d{2}))?", t) if not m: return None return {k: (int(v) if v else 0) for k, v in m.groupdict().items()} for t in ["9:05", "14:30:59", "9:5", "1:2:3"]: print(t, parse_time(t)) # 9:05 {'h': 9, 'm': 5, 's': 0} # 14:30:59 {'h': 14, 'm': 30, 's': 59} # 9:5 None # 1:2:3 None (The code was run and printed exactly the lines shown.) Explanation: the seconds are wrapped in an optional group, (?::(?P\d{2}))?. The outer (?: ... ) is non-capturing and only groups the colon with the digits so that the ? can apply to both. When the seconds are absent, the named group "s" is None, so groupdict() holds None for it and the "if v else 0" turns that into 0. fullmatch rejects "9:5" and "1:2:3" because they do not fit the whole pattern.