Changes in / [11:30241f3a03eb:12:73483c3145ff] in stamper
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
bin/stamps
r3 r10 1 1 #!/usr/bin/env python 2 2 3 import sys3 import argparse 4 4 from stamper import Stamper 5 6 7 def usage(name):8 msg = """9 Usage:10 11 To gather information of recorded times: %(name)s12 13 Recorded times for a given customer: %(name)s customer14 15 Detailed times for a given customer: %(name)s customer details16 """ % {'name': name}17 print(msg)18 5 19 6 20 7 if __name__ == '__main__': 21 8 9 parser = argparse.ArgumentParser( 10 description='stamps: show recorded times information') 11 parser.add_argument('customer', action="store", nargs='?', 12 help='Show times only for this customer') 13 parser.add_argument('filter', action="store", nargs='?', 14 help='Filter the times by date range') 15 parser.add_argument('-v', '--verbose', action="store_true", 16 help='Include detailed times information') 17 18 args = parser.parse_args() 19 22 20 s = Stamper() 23 21 s.load_stamps() 24 25 if len(sys.argv) == 1: 26 totals = s.totals() 27 print('Total times for all customers:') 28 for t in totals: 29 print(' -> %(customer)s: %(total)s' % {'customer': t, 30 'total': totals[t]}) 31 elif len(sys.argv) == 2: 32 if sys.argv[1] in s.customers(): 33 print('Total time for %(customer)s: %(total)s' % { 34 'customer': sys.argv[1], 35 'total': s.total_by_customer(sys.argv[1]) 36 }) 37 38 elif len(sys.argv) == 3: 39 if sys.argv[1] in s.customers(): 40 print('Detailed time for %(customer)s' % { 41 'customer': sys.argv[1], 42 }) 43 details, totals = s.details_by_customer(sys.argv[1]) 44 for day in details: 45 print('------ %(day)s ------' % {'day': day}) 46 for line in details[day]: 47 print(line) 48 print(' Total: %(total)s' % {'total': totals[day]}) 49 50 else: 51 usage(sys.argv[0]) 52 sys.exit(1) 22 s.show_stamps(args.customer, args.filter, args.verbose) -
stamper/stamper.py
r0 r9 1 1 2 2 import json 3 import re 3 4 from datetime import datetime, timedelta 4 5 from os.path import expanduser, exists 6 5 7 6 8 STAMPS_FILE = expanduser('~/.workstamps.json') … … 49 51 return worktime.seconds 50 52 53 def validate_filter(self, stamp_filter): 54 """ 55 Validate a given filter. Filters can have the following notation: 56 57 - %Y-%m-%d--%Y-%m-%d: Times recorded between two dates 58 59 - -%Y-%m-%d: Times recorded before a given date 60 61 - +%Y-%m-%d: Times recorded after a given date 62 63 - N...N[d|w|m|y]: Times recorded N...N days/weeks/months/years ago 64 """ 65 # First try the date filters, one by one 66 matches = ['%Y-%m-%d', '-%Y-%m-%d', '+%Y-%m-%d'] 67 for match in matches: 68 try: 69 if '--' in stamp_filter: 70 filter_from, filter_to = stamp_filter.split('--') 71 filter_from = datetime.strptime(stamp_filter, match) 72 filter_to = datetime.strptime(stamp_filter, match) 73 else: 74 valid_filter = datetime.strptime(stamp_filter, match) 75 except ValueError: 76 pass 77 else: 78 return stamp_filter 79 80 valid_filter = re.search(r'(\d+[dwmyDWMY]{1})', stamp_filter) 81 if valid_filter: 82 return stamp_filter 83 84 # Not a valid filter 85 return None 86 51 87 def customers(self): 52 88 customers = [] … … 57 93 return customers 58 94 59 def total _by_customer(self, customer):60 total = 095 def totals(self, stamp_filter=None): 96 totals = {} 61 97 for stamp in self.stamps: 62 if stamp['customer'] == customer: 63 total += self.worktime(stamp['start'], stamp['end']) 64 total = timedelta(seconds=total) 65 return str(total) 98 customer = stamp['customer'] 99 if customer: 100 # c will be None for "start" stamps, having no end time 101 if customer not in totals: 102 totals[customer] = 0 103 totals[customer] += self.worktime(stamp['start'], stamp['end']) 104 return totals 66 105 67 def totals(self): 106 def details(self): 107 details = {} 68 108 totals = {} 69 for customer in self.customers(): 70 totals[customer] = self.total_by_customer(customer) 71 return totals 109 for stamp in self.stamps: 110 if stamp['customer']: 111 # avoid "start" stamps 112 start_day = stamp['start'].split(' ')[0] 113 if start_day not in details: 114 details[start_day] = [] 115 if start_day not in totals: 116 totals[start_day] = 0 117 worktime = self.worktime(stamp['start'], stamp['end']) 118 details[start_day].append( 119 ' -> %(worktime)s %(customer)s %(action)s' % { 120 'worktime': str(timedelta(seconds=worktime)), 121 'customer': stamp['customer'], 122 'action': stamp['action'] 123 }) 124 totals[start_day] += worktime 125 for day in totals: 126 totals[day] = str(timedelta(seconds=totals[day])) 127 return details, totals 72 128 73 129 def details_by_customer(self, customer): … … 92 148 totals[day] = str(timedelta(seconds=totals[day])) 93 149 return details, totals 150 151 def show_stamps(self, customer=None, stamp_filter=None, verbose=False): 152 if stamp_filter: 153 stamp_filter = self.validate_filter(stamp_filter) 154 155 totals = self.totals(stamp_filter) 156 157 if customer: 158 total = timedelta(seconds=totals.get(customer, 0)) 159 print(' %(customer)s: %(total)s' % {'customer': customer, 160 'total': total}) 161 else: 162 for c in totals: 163 total = timedelta(seconds=totals[c]) 164 print(' %(customer)s: %(total)s' % {'customer': c, 165 'total': total}) 166 167 if verbose: 168 if customer: 169 details, totals = self.details_by_customer(customer) 170 else: 171 details, totals = self.details() 172 for day in details: 173 print('------ %(day)s ------' % {'day': day}) 174 for line in details[day]: 175 print(line) 176 print(' Total: %(total)s' % {'total': totals[day]})
Note:
See TracChangeset
for help on using the changeset viewer.