kyrenia
kyrenia

Reputation: 5575

Convert string to list of dates

I am reading a list of dates which has been saved to a sql file as a string filed - it has the form "[datetime.date(2003, 2, 4), datetime.date(2003, 2, 6)]". Is there a easy way of converting this from the string to the original format again?

[n.b. all i can think of would be to parse it by regex, but I am hoping that there would be an easier way]

Upvotes: 1

Views: 364

Answers (4)

zehnpaard
zehnpaard

Reputation: 6243

Sometimes, regex really is the right tool for the job - I don't think the following code is too complex, and seems pretty explicit in its intention:

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]

If you don't have access to the dateutil module, then you can also roll your own parse function:

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]

Upvotes: 1

Blender
Blender

Reputation: 298582

You could turn your code into something ast.literal_eval can parse and then convert it back into datetime.date objects:

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', ''))]

This avoids the potential security problems of eval while still being reasonably simple.

Upvotes: 4

Boa
Boa

Reputation: 2697

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('),')]

Output:

[datetime.datetime(2003, 4, 2, 0, 0), datetime.datetime(2003, 6, 2, 0, 0)]

Upvotes: 1

Daniel F
Daniel F

Reputation: 14259

This, but eval is dangerous, so you might want to regex it to check if it is of the format you expect.

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

So if you trust your database, you can remove the regex.

Upvotes: 0

Related Questions