1

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]

kyrenia
  • 5,431
  • 9
  • 63
  • 93
  • Do you mean converting from the datetime object to a string? – TerryA Dec 16 '15 at 23:08
  • no - it is in a string field (i.e. `[datetime.date(2003, 2, 4)...`] is just text) - i want to convert it back to a list of dates. – kyrenia Dec 16 '15 at 23:09
  • Wait so the whole thing is a string like so: `"[datetime.date(2003, 2, 4), datetime.date(2003, 2, 6)]"` ? – TerryA Dec 16 '15 at 23:10
  • yes - it was previously a list of dates in python, but was saved to the sql as a string - i want to convert back to list of dates – kyrenia Dec 16 '15 at 23:10
  • like an unwanted crazy uncle in thanksgiving, I could hear the sound of `eval` creeping up on this question – R Nar Dec 16 '15 at 23:11
  • Perhaps you could use the solution from here: http://stackoverflow.com/questions/4235606/python-ast-literal-eval-and-datetime – TerryA Dec 16 '15 at 23:13
  • the correct solution is to fix your upstream data generation process, to avoid parsing Python code. What specific format to use instead depends on your application e.g., `pickle`, `json` may be used in different cases. – jfs Dec 17 '15 at 02:12

4 Answers4

4

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.

Blender
  • 289,723
  • 53
  • 439
  • 496
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('),')]

Output:

[datetime.datetime(2003, 4, 2, 0, 0), datetime.datetime(2003, 6, 2, 0, 0)]
Boa
  • 2,609
  • 1
  • 23
  • 38
1

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]
zehnpaard
  • 6,003
  • 2
  • 25
  • 40
0

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.

Daniel F
  • 13,684
  • 11
  • 87
  • 116
  • `eval` IS dangerous, so I see no reason why you would suggest it at all – TerryA Dec 16 '15 at 23:13
  • @TerryA There, updated the warning. That should void your argument. – Daniel F Dec 16 '15 at 23:15
  • Well then that's not really your answer is it. You're basically saying "don't do x, do y, but here's x". Show 'y' :) – TerryA Dec 16 '15 at 23:17
  • @TerryA Updated the code. But actually the question does not ask about security related stuff. This is one valid application for eval, regardless of the security implications. – Daniel F Dec 16 '15 at 23:25