Code:
#!/usr/bin/env python
import re, sys, time
days_long = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday']
days_short = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']
months_long = ['january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december']
months_short = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec']
taskexpr = re.compile(r'(.*)\s+due\s+(.*)')
tomorrowexpr = re.compile(r'.*?(((\d+)\s+days\s+after\s+)|(the\s+day\s+after\s+)+)?(tomorrow)')
inxdaysexpr = re.compile(r'.*?in\s+(\d+)\s+days')
weekdayexpr = re.compile(r'(' + '|'.join(days_long + days_short) + r')')
dateexpr = re.compile(r'(\d\d?)\W+(([a-z]+)|(\d\d?))\W+(\d\d(\d\d)?)')
date2expr = re.compile(r'the (\d\d?)(st|nd|th) of (' + '|'.join(months_long) + r') (\d\d(\d\d)?)')
today_year = int(time.strftime('%Y'))
today_month = int(time.strftime('%m'))
today_day = int(time.strftime('%d'))
today_weekday = int(time.strftime('%w'))
tasks = []
def to_int_time(year, month, day, add_days = 0):
date = '{0:04d} {1:02d} {2:02d}'.format(year, month, day)
date = time.mktime(time.strptime(date, '%Y %m %d'))
date += 86400 * add_days # 86400 seconds in a day
return date
def parse_tomorrow(match):
days = 1
if match.group(4): # the day after
days += len([i for i in match.group(1).split() if i == 'after']) # just count the number of afters
elif match.group(2): # n days after
days += int(match.group(3))
return to_int_time(today_year, today_month, today_day, days)
def parse_inxdays(match):
return to_int_time(today_year, today_month, today_day, int(match.group(1)))
def parse_weekday(match):
day = match.group(1)
if day in days_long:
day = days_long.index(day) + 1 # +1 because monday is 1 instead of 0
if day in days_short:
day = days_short.index(day) + 1
day = (day - today_weekday) % 7
if day == 0: day = 7 # make sure it is always the next xxxday, and not today
return to_int_time(today_year, today_month, today_day, day)
def parse_date(match):
day = int(match.group(1))
year = int(match.group(5))
if year < 100:
year += 2000
if match.group(4):
month = int(match.group(4))
elif match.group(3):
month = match.group(3)
if month in months_long:
month = months_long.index(month) + 1 # +1 because january should be 1 instead of 0
elif month in months_short:
month = months_short.index(month) + 1
else:
#invalid month
return None
return to_int_time(year, month, day)
def parse_date2(match):
day = int(match.group(1))
month = months_long.index(match.group(3)) + 1
year = int(match.group(4))
if year < 100:
year += 2000
return to_int_time(year, month, day)
def parse(date):
match = tomorrowexpr.match(date)
if match:
return parse_tomorrow(match)
match = inxdaysexpr.match(date)
if match:
return parse_inxdays(match)
match = weekdayexpr.match(date)
if match:
return parse_weekday(match)
match = dateexpr.match(date)
if match:
return parse_date(match)
match = date2expr.match(date)
if match:
return parse_date2(match)
# everything failed
return None
while True:
input = sys.stdin.readline()
if not input:
break
match = taskexpr.match(input)
if not match:
# print warning
continue
title = match.group(1)
date = parse(match.group(2).strip().lower())
tasks.append((date, title))
tasks = [i for i in tasks if i[0] != None]
tasks.sort()
sys.stdout.write('Today is {0:s}, your tasks:\n'.format(time.strftime('%d %B %Y')))
for t in tasks:
sys.stdout.write('{0:s} due {1:s}\n'.format(t[1], time.strftime('%d %B %Y', time.localtime(t[0]))))
and my test input:
Bookmarks