from datetime import datetime, timedelta import re class Command: def __init__(self, cmdline, default_time = None): if default_time is None: self.time = datetime.now() else: self.time = default_time self.command = 'start' self.argstr = '' self.parseCommandLine(cmdline) def __str__(self): return "{'time' => '%s', 'command' => '%s', 'argstr' => '%s'}" % \ (self.time, self.command, self.argstr) def parseCommandLine(self, cmdline): COMMANDS = { 'out' : 1, 'report' : 1, 'status' : 1, 'fill' : 1, 'adjust' : 1, 'start' : 1, 'task' : 1 } ALIASES = { 'rpt' : 'report', 'adj' : 'adjust', 'end' : 'out', 'st' : 'status', 'show' : 'status', 'f' : 'fill' } args = [] foundArgs = False while True: cmdline = cmdline.strip() if len(cmdline) < 1: break parts = cmdline.split(None, 1) token = parts[0] if not foundArgs: if self.parseDate(token): pass elif self.parseTime(token): pass elif token in COMMANDS: self.command = token foundArgs = True elif token in ALIASES: self.command = ALIASES[token] foundArgs = True else: foundArgs = True args.append(token) else: args.append(token) if len(parts) < 2: break cmdline = parts[1] self.argstr = ' '.join(args) def parseDate(self, dt): if dt.lower() == "yesterday": today = datetime.today() y = today - timedelta(days = 1) self.time = self.time.replace( year = y.year, month = y.month, day = y.day) return True m = re.match('^(?:(\d{4})[-/])?(\d{1,2})[-/](\d{1,2})$', dt) if m is not None: # dt was a date string if m.group(1) is not None: self.time = self.time.replace(year = int(m.group(1))) month, day = int(m.group(2)), int(m.group(3)) self.time = self.time.replace(month = month, day = day) return True return False def parseTime(self, timespec): m = re.match('^(\d{1,2}):?(\d{2})?(am?|pm?)?$', timespec, re.I) if m is not None: # an absolute time was given h = int(m.group(1)) mins = 0 if m.group(2) is None else int(m.group(2)) am_pm = '' if m.group(3) is None else m.group(3)[0].lower() if am_pm == 'p' and h < 12: h += 12 elif am_pm == 'a' and h == 12: h = 0 self.time = self.time.replace(hour = h, minute = mins, second = 0) return True m = re.match('^([-+])(\d+(?:\.\d+)?)([hms])?$', timespec, re.I) if m is not None: # a relative time was given plus_minus = m.group(1) hms = '' if m.group(3) is None else m.group(3) count = int(m.group(2)) if hms == 'm': seconds = count * 60 elif hms == 's': seconds = count else: # hours seconds = count * 60 * 60 delta = timedelta(seconds = seconds) if plus_minus == '-': self.time -= delta else: self.time += delta return True return False