Я читаю список дат, который был сохранен в файл sql в виде строки строки - он имеет вид "[datetime.date(2003, 2, 4), datetime.date(2003, 2, 6)]". Есть ли простой способ снова преобразовать это из строки в исходный формат?

[ Нотабене все, что я могу придумать, это разобрать его с помощью регулярных выражений, но я надеюсь, что будет более легкий путь]

0
kyrenia 17 Дек 2015 в 02:06

4 ответа

Лучший ответ

Вы можете превратить ваш код во что-то, что ast.literal_eval может проанализировать, а затем преобразовать его обратно в datetime.date объекты:

import ast
import datetime

d = "[datetime.date(2003, 2, 4), datetime.date(2003, 2, 6)]"
dates = [datetime.date(*args) for args in ast.literal_eval(d.replace('datetime.date', ''))]

Это позволяет избежать потенциальных проблем безопасности eval, оставаясь при этом достаточно простым.

3
Blender 17 Дек 2015 в 00:09

Иногда regex действительно является подходящим инструментом для работы - я не думаю, что следующий код слишком сложен и кажется довольно явным в своем намерении:

from dateutil.parser import parse
import re

s = "[datetime.date(2003, 2, 4), datetime.date(2003, 2, 6)]"
c = re.compile("datetime.date\((.*?)\)")
date_strings = c.findall(s)
print [parse(date_string).date() for date_string in date_strings]

Если у вас нет доступа к модулю dateutil, вы также можете свернуть свою собственную функцию parse:

import datetime
import re

def parse(s):
    year, month, day = s.split(', ')
    year, month, day = int(year), int(month), int(day)
    return datetime.date(year, month, day)

s = "[datetime.date(2003, 2, 4), datetime.date(2003, 2, 6)]"
c = re.compile("datetime.date\((.*?)\)")
date_strings = c.findall(s)
print [parse(date_string) for date_string in date_strings]
1
zehnpaard 17 Дек 2015 в 05:46
from dateutil.parser import parse

d = "[datetime.date(2003, 2, 4), datetime.date(2003, 2, 6)]"

reverse_date = lambda x: ','.join(x.split(',')[::-1])
clean_up = lambda x: x.replace('datetime.date(','').replace(')','')

[parse(reverse_date(clean_up(x))) for x in d[1:-1].split('),')]

Выход:

[datetime.datetime(2003, 4, 2, 0, 0), datetime.datetime(2003, 6, 2, 0, 0)]
1
Boa 16 Дек 2015 в 23:47

Это, но eval опасен, поэтому вы можете захотеть пересмотреть его, чтобы проверить, соответствует ли он ожидаемому формату.

import re
import datetime
strdates = "[datetime.date(2003, 2, 4), datetime.date(2003, 2, 6)]"
if re.search(r"\[(datetime\.date\(\d{4},\ *\d{1,2},\ *\d{1,2}\),?\ *)+]", strdates):
  dates = eval(strdates)
  for date in dates:
    print date

Поэтому, если вы доверяете своей базе данных, вы можете удалить регулярное выражение.

0
Daniel F 16 Дек 2015 в 23:23