解析工作时间字符串的正则表达式模式

3 投票
3 回答
1281 浏览
提问于 2025-04-17 15:04

我正在写一个Python库,用来解析不同的工作时间字符串,并把它们转换成标准的时间格式。不过我在处理以下情况时遇到了困难:

我的正则表达式应该能把 Mon - Fri 7am - 5pm Sat 9am - 3pm 这段文字分成 ['Mon - Fri 7am - 5pm ', 'Sat 9am - 3pm'] 这样的两部分,但如果中间有个逗号,就应该返回 []

而且,逗号可以出现在任何地方,但不能出现在两个工作日和时间段之间。比如说:Mon - Fri 7am - 5pm Sat 9am - 3pm and available upon email, phone call 这段文字应该返回 ['Mon - Fri 7am - 5pm ', 'Sat 9am - 3pm']

这是我尝试过的:

import re
pattern = """(
    (?:mon|tue|wed|thu|fri|sat|sun|mo|tu|we|th|fr|sa|su|m|w|f|thurs) # Start weekday
\s*[-|to]+\s* # Seperator
(?:mon|tue|wed|thu|fri|sat|sun|mo|tu|we|th|fr|sa|su|^(?![ap])m|w|f|thurs)?  # End weekday
\s*[from]*\s* # Seperator
(?:\d{1,2}(?:[:]\d{1,2})?)\s*(?:[ap][.]?m.?) # Start hour
\s*[-|to]+\s* # Seperator
(?:\d{1,2}(?:[:]\d{1,2})?)\s*(?:[ap][.]?m.?) # Close hour
)"""

regEx = re.compile(pattern, re.IGNORECASE|re.VERBOSE)

print re.findall(regEx, "Mon - Fri 7am - 5pm Sat 9am - 3pm")
# output ['Mon - Fri 7am - 5pm ', 'Sat 9am - 3pm']
print re.findall(regEx, "Mon - Fri 7am - 5pm Sat - Sun 9am - 3pm")
# output ['Mon - Fri 7am - 5pm ', 'Sat - Sun 9am - 3pm']
print re.findall(regEx, "Mon - Fri 7am - 5pm, Sat 9am - 3pm")
# expected output []
# but I get ['Mon - Fri 7am - 5pm,', 'Sat 9am - 3pm']
print re.findall(regEx, "Mon - Fri 7am - 5pm , Sat 9am - 3pm")
# expected output []
# but I get ['Mon - Fri 7am - 5pm ', 'Sat 9am - 3pm']

我还在我的正则表达式中尝试了负向前瞻模式。

pattern = """(
(?:mon|tue|wed|thu|fri|sat|sun|mo|tu|we|th|fr|sa|su|m|w|f|thurs)
\s*[-|to]+\s*
(?:mon|tue|wed|thu|fri|sat|sun|mo|tu|we|th|fr|sa|su|^(?![ap])m|w|f|thurs)?
\s*[from]*\s*
(?:\d{1,2}(?:[:]\d{1,2})?)\s*(?:[ap][.]?m.?)
\s*[-|to]+\s*
(?:\d{1,2}(?:[:]\d{1,2})?)\s*(?:[ap][.]?m.?)
(?![^,])
)"""

但是我没有得到预期的结果。我是不是应该明确写代码来检查这个条件?有没有办法只通过修改我的正则表达式,而不需要写额外的条件检查呢?

我还有一个想法,就是如果没有逗号的话,就在两个工作日和时间段之间加上逗号,然后把我的正则表达式改成按逗号分组或分割。比如说:"Mon - Fri 7am - 5pm Sat 9am - 3pm" 可以变成 "Mon - Fri 7am - 5pm, Sat 9am - 3pm"

3 个回答

0

我没法用一个正则表达式搞定这个,真的很难,你的问题挺好的。
我可以帮你实现你需要的功能,但要提醒你,我对此并不太自豪。

假设你有一个函数可以做到这一点……

def sample_funct(unparsed_schedule)
    result = []

    # Day Pattern
    pattern = """
    (?:mon|tue|wed|thu|fri|sat|sun|mo|tu|we|th|fr|sa|su|m|w|f|thurs) # Start weekday
    \s*[-|to]+\s* # Seperator
    (?:mon|tue|wed|thu|fri|sat|sun|mo|tu|we|th|fr|sa|su|^(?![ap])m|w|f|thurs)?  # End weekday
    \s*[from]*\s* # Seperator
    (?:\d{1,2}(?:[:]\d{1,2})?)\s*(?:[ap][\.]?m\.?) # Start hour
    \s*[-|to]+\s* # Seperator
    (?:\d{1,2}(?:[:]\d{1,2})?)\s*(?:[ap][\.]?m\.?) # Close hour
    """

    # No commas pattern
    pattern2 = "%s\s*[^,]\s*%s" % (pattern, pattern)

    # Actual Regex Pattern Items
    schedule     = re.compile(pattern, re.IGNORECASE|re.VERBOSE)
    remove_comma = re.compile(pattern2, re.IGNORECASE|re.VERBOSE)

    # Check we have no commas in the middle
    valid_result = re.search(remove_comma, unparsed_schedule)
    if valid_result:
        # Positive result, return the list with schedules
        result = re.findall(schedule, validresult.group(0))

    # If no valid results will return empty list
    return result 
0

我写了几行代码,用来检查并在每个工作日的时间段之间加上逗号,如果原本没有的话。这样我就能得到一个统一的格式,比如"周一 - 周五 早上7点 - 下午5点, 周六 早上9点 - 下午3点",然后我就可以继续进行其他操作了。

1

我觉得你可以通过匹配整个表达式来简单地做到这一点,这样就不允许出现逗号(以及其他字符):

pattern = """^(
(
    (?:mon|tue|wed|thu|fri|sat|sun|mo|tu|we|th|fr|sa|su|m|w|f|thurs) # Start weekday
\s*[-|to]+\s* # Seperator
(?:mon|tue|wed|thu|fri|sat|sun|mo|tu|we|th|fr|sa|su|^(?![ap])m|w|f|thurs)?  # End weekday
\s*[from]*\s* # Seperator
(?:\d{1,2}(?:[:]\d{1,2})?)\s*(?:[ap][.]?m.?) # Start hour
\s*[-|to]+\s* # Seperator
(?:\d{1,2}(?:[:]\d{1,2})?)\s*(?:[ap][.]?m.?) # Close hour
)
)+$""

这样会输出:

[('Sat 9am - 3pm', 'Sat 9am - 3pm')]
[('Sat - Sun 9am - 3pm', 'Sat - Sun 9am - 3pm')]
[]
[]

希望这对你有帮助,

撰写回答