Index: bin/stamps
===================================================================
--- bin/stamps	(revision 3)
+++ bin/stamps	(revision 10)
@@ -1,52 +1,22 @@
 #!/usr/bin/env python
 
-import sys
+import argparse
 from stamper import Stamper
-
-
-def usage(name):
-    msg = """
-    Usage:
-
-    To gather information of recorded times: %(name)s
-
-    Recorded times for a given customer: %(name)s customer
-
-    Detailed times for a given customer: %(name)s customer details
-    """ % {'name': name}
-    print(msg)
 
 
 if __name__ == '__main__':
 
+    parser = argparse.ArgumentParser(
+        description='stamps: show recorded times information')
+    parser.add_argument('customer', action="store", nargs='?',
+                        help='Show times only for this customer')
+    parser.add_argument('filter', action="store", nargs='?',
+                        help='Filter the times by date range')
+    parser.add_argument('-v', '--verbose', action="store_true",
+                        help='Include detailed times information')
+
+    args = parser.parse_args()
+
     s = Stamper()
     s.load_stamps()
-
-    if len(sys.argv) == 1:
-        totals = s.totals()
-        print('Total times for all customers:')
-        for t in totals:
-            print(' -> %(customer)s: %(total)s' % {'customer': t,
-                                                   'total': totals[t]})
-    elif len(sys.argv) == 2:
-        if sys.argv[1] in s.customers():
-            print('Total time for %(customer)s: %(total)s' % {
-                'customer': sys.argv[1],
-                'total': s.total_by_customer(sys.argv[1])
-                })
-
-    elif len(sys.argv) == 3:
-        if sys.argv[1] in s.customers():
-            print('Detailed time for %(customer)s' % {
-                'customer': sys.argv[1],
-                })
-            details, totals = s.details_by_customer(sys.argv[1])
-            for day in details:
-                print('------ %(day)s ------' % {'day': day})
-                for line in details[day]:
-                    print(line)
-                print(' Total: %(total)s' % {'total': totals[day]})
-
-    else:
-        usage(sys.argv[0])
-        sys.exit(1)
+    s.show_stamps(args.customer, args.filter, args.verbose)
Index: stamper/stamper.py
===================================================================
--- stamper/stamper.py	(revision 0)
+++ stamper/stamper.py	(revision 9)
@@ -1,6 +1,8 @@
 
 import json
+import re
 from datetime import datetime, timedelta
 from os.path import expanduser, exists
+
 
 STAMPS_FILE = expanduser('~/.workstamps.json')
@@ -49,4 +51,38 @@
         return worktime.seconds
 
+    def validate_filter(self, stamp_filter):
+        """
+        Validate a given filter. Filters can have the following notation:
+
+        - %Y-%m-%d--%Y-%m-%d: Times recorded between two dates
+
+        - -%Y-%m-%d: Times recorded before a given date
+
+        - +%Y-%m-%d: Times recorded after a given date
+
+        - N...N[d|w|m|y]: Times recorded N...N days/weeks/months/years ago
+        """
+        # First try the date filters, one by one
+        matches = ['%Y-%m-%d', '-%Y-%m-%d', '+%Y-%m-%d']
+        for match in matches:
+            try:
+                if '--' in stamp_filter:
+                    filter_from, filter_to = stamp_filter.split('--')
+                    filter_from = datetime.strptime(stamp_filter, match)
+                    filter_to = datetime.strptime(stamp_filter, match)
+                else:
+                    valid_filter = datetime.strptime(stamp_filter, match)
+            except ValueError:
+                pass
+            else:
+                return stamp_filter
+
+        valid_filter = re.search(r'(\d+[dwmyDWMY]{1})', stamp_filter)
+        if valid_filter:
+            return stamp_filter
+
+        # Not a valid filter
+        return None
+
     def customers(self):
         customers = []
@@ -57,17 +93,37 @@
         return customers
 
-    def total_by_customer(self, customer):
-        total = 0
+    def totals(self, stamp_filter=None):
+        totals = {}
         for stamp in self.stamps:
-            if stamp['customer'] == customer:
-                total += self.worktime(stamp['start'], stamp['end'])
-        total = timedelta(seconds=total)
-        return str(total)
+            customer = stamp['customer']
+            if customer:
+                # c will be None for "start" stamps, having no end time
+                if customer not in totals:
+                    totals[customer] = 0
+                totals[customer] += self.worktime(stamp['start'], stamp['end'])
+        return totals
 
-    def totals(self):
+    def details(self):
+        details = {}
         totals = {}
-        for customer in self.customers():
-            totals[customer] = self.total_by_customer(customer)
-        return totals
+        for stamp in self.stamps:
+            if stamp['customer']:
+                # avoid "start" stamps
+                start_day = stamp['start'].split(' ')[0]
+                if start_day not in details:
+                    details[start_day] = []
+                if start_day not in totals:
+                    totals[start_day] = 0
+                worktime = self.worktime(stamp['start'], stamp['end'])
+                details[start_day].append(
+                    ' -> %(worktime)s %(customer)s %(action)s' % {
+                        'worktime': str(timedelta(seconds=worktime)),
+                        'customer': stamp['customer'],
+                        'action': stamp['action']
+                    })
+                totals[start_day] += worktime
+        for day in totals:
+            totals[day] = str(timedelta(seconds=totals[day]))
+        return details, totals
 
     def details_by_customer(self, customer):
@@ -92,2 +148,29 @@
             totals[day] = str(timedelta(seconds=totals[day]))
         return details, totals
+
+    def show_stamps(self, customer=None, stamp_filter=None, verbose=False):
+        if stamp_filter:
+            stamp_filter = self.validate_filter(stamp_filter)
+
+        totals = self.totals(stamp_filter)
+
+        if customer:
+            total = timedelta(seconds=totals.get(customer, 0))
+            print(' %(customer)s: %(total)s' % {'customer': customer,
+                                                'total': total})
+        else:
+            for c in totals:
+                total = timedelta(seconds=totals[c])
+                print(' %(customer)s: %(total)s' % {'customer': c,
+                                                    'total': total})
+
+        if verbose:
+            if customer:
+                details, totals = self.details_by_customer(customer)
+            else:
+                details, totals = self.details()
+            for day in details:
+                print('------ %(day)s ------' % {'day': day})
+                for line in details[day]:
+                    print(line)
+                print(' Total: %(total)s' % {'total': totals[day]})
