HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Track hours worked total or per month

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
totaltrackperworkedhoursmonth

Problem

I track the hours that I have worked on something in an Excel sheet (actually Google Spreadsheet, but semantics). This is tracked in the following format:

Date | Start (time) | End (time) | Description

I can download this as a CSV and my program will run through it and tell me how many hours I've worked in total and per month. It can also calculate the tax that will go over it. (Keep in mind, these are Dutch taxes).

CSV example:

Date,Start,End,Description
2016-11-11,16:00,16:45,Demo


hours.py:

`#!/usr/bin/env python
# -- encoding: utf-8 --
"""
This script reads the worked hours from CSV file generated from
Google docs / Excel and generates statistics from it.

The CSV file should be in format:
Date,Start,End,Description

"""
import argparse
import csv
import os

from models import Stats

def hours_minutes(td):
"""Converts timedelta object into hours and minutes"""
return (td.seconds // 3600) + (td.days * 24), (td.seconds // 60) % 60

def calculate_salary(rate, td, tax=0):
"""
Calculates the salary based on the amount of time worked.
Tax is deduced from the total amount, not the hourly rate.
:rate: The hourly rate
:td: timedelta with the amount of time worked.
"""
hours, minutes = hours_minutes(td)
total = hours * rate

if minutes: # to prevent ZeroDivisionError
total += (minutes / 60.0) * rate

if tax:
total = total - (total / 100 * tax)

return total

def print_salary(args, total_time, prepend=''):
"""
Prints the total salary and the total salary with the taxes taken off.

:args: The command line args from argparse
:total_time: Timedelta that will be used to print the number of hours
:prepend: String to prepend to the print out. For example '\t' for indent.
"""
print(prepend + 'Total salary: €{salary:.2f}'.format(
salary=calculate_salary(args['rate'], total_time)))
print(prepend + 'Total salary taxed: €{salary:.2f} tax: {tax:.2f}%'.format

Solution

Division by zero?

if minutes:  # to prevent ZeroDivisionError
    total += (minutes / 60.0) * rate

if tax:
    total = total - (total / 100 * tax)


So what if minutes = 0? Then total = (0 / 60.0) * rate = 0 It doesn't cause a division error. Same goes for tax = 0.

(Also, if you think that minutes could become 1/0 or some other sort of indeterminate form, the program will fail well before you get to that if statement.)

Reducing over addition

You write reduce(operator.add ... ) a few times. There is common name for this operation, it's called sum, and it is included by default, so you should be able to get rid of import operator all together.

Code Snippets

if minutes:  # to prevent ZeroDivisionError
    total += (minutes / 60.0) * rate

if tax:
    total = total - (total / 100 * tax)

Context

StackExchange Code Review Q#151475, answer score: 2

Revisions (0)

No revisions yet.