I have strings that show a date in the following format:
x minutes/hours/days/months/years ago
I need to parse that to a datetime using pyt
completely exaggerated solution but I needed something more flexible:
def string_to_delta(relative):
#using simplistic year (no leap months are 30 days long.
#WARNING: 12 months != 1 year
unit_mapping = [('mic', 'microseconds', 1),
('millis', 'microseconds', 1000),
('sec', 'seconds', 1),
('day', 'days', 1),
('week', 'days', 7),
('mon', 'days', 30),
('year', 'days', 365)]
try:
tokens = relative.lower().split(' ')
past = False
if tokens[-1] == 'ago':
past = True
tokens = tokens[:-1]
elif tokens[0] == 'in':
tokens = tokens[1:]
units = dict(days = 0, seconds = 0, microseconds = 0)
#we should always get pairs, if not we let this die and throw an exception
while len(tokens) > 0:
value = tokens.pop(0)
if value == 'and': #just skip this token
continue
else:
value = float(value)
unit = tokens.pop(0)
for match, time_unit, time_constant in unit_mapping:
if unit.startswith(match):
units[time_unit] += value * time_constant
return datetime.timedelta(**units), past
except Exception as e:
raise ValueError("Don't know how to parse %s: %s" % (relative, e))
This can parse things like:
2 days agoin 60 seconds2 DAY and 4 Secsin 1 year, 1 Month, 2 days and 4 MICRO2 Weeks 4 secs ago7 millis agoA huge but: It simplifies month and year to 30 and 365 days respectively. Not always what you want, though it's enough for some cases.