Единственный метод Calendar
, который возвращает эту информацию, это nlp()
(что, я полагаю, означает обработку естественного языка). Вот функция, возвращающая все части ввода:
import parsedatetime
calendar = parsedatetime.Calendar()
def parse(string, source_time = None):
ret = []
parsed_parts = calendar.nlp(string, source_time)
if parsed_parts:
last_stop = 0
for part in parsed_parts:
dt, status, start, stop, segment = part
if start > last_stop:
ret.append((None, 0, string[last_stop:start]))
ret.append((dt, status, segment))
last_stop = stop
if len(string) > last_stop:
ret.append((None, 0, string[last_stop:]))
return ret
for s in ("Soccer with @homies at Payne Whitney tomorrow at 2 pm to 4 pm!",
"Soccer with @homies at Payne Whitney tomorrow starting at 2 pm to 4 pm!",
"Soccer with @homies at Payne Whitney tomorrow starting at 3 pm to 5 pm!"):
print()
print(s)
result = parse(s)
for part in result:
print(part)
Вывод:
Soccer with @homies at Payne Whitney tomorrow at 2 pm to 4 pm!
(None, 0, 'Soccer with @homies at Payne Whitney ')
(datetime.datetime(2020, 1, 15, 16, 0), 3, 'tomorrow at 2 pm to 4 pm')
(None, 0, '!')
Soccer with @homies at Payne Whitney tomorrow starting at 2 pm to 4 pm!
(None, 0, 'Soccer with @homies at Payne Whitney ')
(datetime.datetime(2020, 1, 15, 9, 0), 1, 'tomorrow')
(None, 0, ' starting ')
(datetime.datetime(2020, 1, 14, 16, 0), 2, 'at 2 pm to 4 pm')
(None, 0, '!')
Soccer with @homies at Payne Whitney tomorrow starting at 3 pm to 5 pm!
(None, 0, 'Soccer with @homies at Payne Whitney ')
(datetime.datetime(2020, 1, 15, 9, 0), 1, 'tomorrow')
(None, 0, ' starting ')
(datetime.datetime(2020, 1, 14, 15, 0), 2, 'at 3 pm')
(None, 0, ' to ')
(datetime.datetime(2020, 1, 14, 17, 0), 2, '5 pm')
(None, 0, '!')
status
сообщает вам, является ли связанный datetime
фактической датой (1
), время (2
), дата / время (3
) или нет (0
). В первых двух случаях пропущенные поля берутся из source_time
или из текущего времени, если это None
.
Но если вы внимательно изучите вывод, вы увидите, что есть проблема надежности здесь. Можно использовать только третий анализ, в двух других случаях информация была потеряна. Кроме того, я понятия не имею, почему вторая и третья строки будут анализироваться по-разному.
Альтернативная библиотека - dateparser
. Он выглядит мощнее, но имеет свои проблемы. Функция dateparser.parse.search_dates()
приближается к тому, что вас интересует, но я не смог выяснить, как определить, передает ли обработанный datetime
только информацию о дате, только информацию о времени или и то, и другое. В любом случае, вот функция, которая использует search_dates()
для получения вывода, аналогичного приведенному выше, но без status
каждой части:
from dateparser.search import search_dates
def parse(string: str):
ret = []
parsed_parts = search_dates(string)
if parsed_parts:
last_stop = 0
for part in parsed_parts:
segment, dt = part
start = string.find(segment, last_stop)
stop = start + len(segment)
if start > last_stop:
ret.append((None, string[last_stop:start]))
ret.append((dt, segment))
last_stop = stop
if len(string) > last_stop:
ret.append((None, string[last_stop:]))
return ret
for s in ("Soccer with @homies at Payne Whitney tomorrow at 2 pm to 4 pm!",
"Soccer with @homies at Payne Whitney tomorrow starting at 2 pm to 4 pm!",
"Soccer with @homies at Payne Whitney tomorrow starting at 3 pm to 5 pm!"):
print()
print(s)
result = parse(s)
for part in result:
print(part)
Вывод:
Soccer with @homies at Payne Whitney tomorrow at 2 pm to 4 pm!
(None, 'Soccer with @homies at Payne Whitney ')
(datetime.datetime(2020, 1, 15, 14, 0), 'tomorrow at 2 pm')
(None, ' to ')
(datetime.datetime(2020, 1, 13, 16, 0), '4 pm')
(None, '!')
Soccer with @homies at Payne Whitney tomorrow starting at 2 pm to 4 pm!
(None, 'Soccer with @homies at Payne Whitney ')
(datetime.datetime(2020, 1, 15, 0, 43, 0, 726130), 'tomorrow')
(None, ' starting ')
(datetime.datetime(2020, 1, 13, 14, 0), 'at 2 pm')
(None, ' to ')
(datetime.datetime(2020, 1, 13, 16, 0), '4 pm')
(None, '!')
Soccer with @homies at Payne Whitney tomorrow starting at 3 pm to 5 pm!
(None, 'Soccer with @homies at Payne Whitney ')
(datetime.datetime(2020, 1, 15, 0, 43, 0, 784468), 'tomorrow')
(None, ' starting ')
(datetime.datetime(2020, 1, 13, 15, 0), 'at 3 pm')
(None, ' to ')
(datetime.datetime(2020, 1, 13, 17, 0), '5 pm')
(None, '!')
Я думаю, что поиск подстроки во входных данных является приемлемым, и синтаксический анализ кажется более предсказуемым, но проблема не в том, как интерпретировать каждый datetime
.