2015-12-16 4 views
0

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

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

+0

вы имеете в виду преобразование от объекта даты и времени в строку? – TerryA

+0

no - он находится в строковом поле (т. Е. '[Datetime.date (2003, 2, 4) ...'] - это просто текст) - я хочу преобразовать его в список дат. – kyrenia

+0

Подождите, так что вся строка будет такой: '' [datetime.date (2003, 2, 4), datetime.date (2003, 2, 6)] "'? – TerryA

ответ

3

Вы можете превратить ваш код в нечто 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 при этом все еще достаточно прост.

0

Это, но 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

'eval' Опасно, поэтому я не вижу причин, почему вы предлагаете его вообще – TerryA

+0

@TerryA Там обновлено предупреждение. Это должно аннулировать ваш аргумент. –

+0

Хорошо, тогда это не ваш ответ. Вы в основном говорите: «Не делайте x, y, но вот x». Показать 'y' :) – TerryA

1
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

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

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] 
Смежные вопросы