Python strptime с переменным текстом - PullRequest
0 голосов
/ 31 января 2019

У меня есть список дат в виде строк.Выглядит это так:

[
  "January 29-30 Meeting - 2013",
  "March 19-20 Meeting - 2013",
  "April/May 30-1 Meeting - 2013",
  "June 18-19 Meeting - 2013",
  "July 30-31 Meeting - 2013",
  "September 17-18 Meeting - 2013",
  "October 29-30 Meeting - 2013",
  "December 17-18 Meeting - 2013"
]

Мне нужно проанализировать эти даты в формате datetime.

datetime.strptime("January 29-30 Meeting - 2013", "%B %d-[something] - %Y")
datetime.strptime("January 29-30 Meeting - 2013", "%B [something]-%d [something] - %Y")

Есть ли способ указать strptime в спецификаторе формата, чтобыигнорировать текст в [something], так как он может быть переменным?Есть ли спецификатор формата для переменного текста?

Ответы [ 2 ]

0 голосов
/ 31 января 2019

Вы можете переопределить объект _strptime.TimeRE с помощью дополнительной директивы, которая лениво соответствует любой последовательности символов:

from datetime import datetime
import _strptime
TimeRE = _strptime.TimeRE()
TimeRE.update({'x': '.*?'})
_strptime._TimeRE_cache = TimeRE
print(datetime.strptime("January 29-30 Meeting - 2013", "%B %d-%x - %Y"))

Это выводит:

2013-01-29 00:00:00
0 голосов
/ 31 января 2019

Для strptime нет директивы с подстановочными знаками.Вы можете увидеть список директив здесь https://docs.python.org/3/library/time.html#time.strftime

Разумный способ решить вашу проблему - объединить регулярное выражение с strptime.Т.е. отфильтруйте текст с помощью регулярного выражения и поместите оставшийся ограниченный текст в strptime или просто передав соответствующие группы непосредственно в datetime.

import re
from datetime import datetime

ss = [
  "January 29-30 Meeting - 2013",
  "March 19-20 Meeting - 2013",
  "April/May 30-1 Meeting - 2013",
  "June 18-19 Meeting - 2013",
  "July 30-31 Meeting - 2013",
  "September 17-18 Meeting - 2013",
  "October 29-30 Meeting - 2013",
  "December 17-18 Meeting - 2013"
]

FORMAT = '%B %d %Y'

for s in ss:
    match = re.search(r"(\w+)\s(\d+)-(\d+)\s.*\s(\d{4})", s)
    if match:
        dt1 = datetime.strptime(f'{match.group(1)} {match.group(2)} {match.group(4)}', FORMAT)
        dt2 = datetime.strptime(f'{match.group(1)} {match.group(3)} {match.group(4)}', FORMAT)

        print (dt1, dt2)

Обратите внимание, что у вас также есть April/May 30-1 сложность там, я не обращаюсь к этому, так как вы не спрашиваете об этом.

В качестве бонуса, хотя:

for s in ss:
    match = re.search(r"((\w+)/)?(\w+)\s(\d+)-(\d+)\s.*\s(\d{4})", s)
    if match:
        dt1 = datetime.strptime(
            f'{match.group(2) if match.group(2) else match.group(3)} {match.group(4)} {match.group(6)}', FORMAT)
        dt2 = datetime.strptime(
            f'{match.group(3)} {match.group(5)} {match.group(6)}', FORMAT)

        print (dt1, dt2)

Кроме того, обратите внимание на интересное, если немногохакерское решение, предлагаемое @blhsing ниже, включающее _strptime.TimeRE.Я бы не рекомендовал делать что-либо подобное, но интересно знать, что вы могли бы таким образом изменить поведение самой strptime.

...