A simple hour tracker for git
Project description
Hourly
A simple hour tracker for git projects. hourly
parses your commit messages for "clock in/out" keywords and uses their unix timestamps to precisely calculate work hours.
Getting Started
Install
pip install hourly
Requirements
pandas
gitpython
Usage
Hourly will look for key words for clocking in/out.
To clock in:
git commit -m "clock in - starting work on new feature"
do stuff as usual, then clock out
git commit -m "clock out - finished feature"
Tutorial
We can illustrate how to use hourly on the hourly repo itself.
git clone https://github.com/asherp/hourly.git
cd hourly
from hourly.hourly import get_work_commits, get_labor, get_earnings
get_work_commits
gathers all commits into a pandas array
work = get_work_commits('.')
work
message | hash | |
---|---|---|
time | ||
2018-10-19 23:40:41-04:00 | Initial commit | ef5690543bfb354b9325d1fbd1f9abbafbb4d9a4 |
2018-10-19 23:57:48-04:00 | clock in\n | 5c8f05b57b739ec525291c248ea9200651b49997 |
2018-10-20 00:21:40-04:00 | preparing setup.py\n | 254ecdacb52fc70bc358f8d55be58df3b70c7609 |
2018-10-20 00:39:11-04:00 | clock out - work done for the day\n | 0e33fa3d74f663f954b05dd9f30e0128ca7af162 |
2018-10-20 01:06:08-04:00 | clock in - start adding requirements and examp... | dc065b17337b14c2f8e0458de61e6880a338d6ae |
2018-10-20 01:47:01-04:00 | clock out\n | 644ad6ebf4c9015fd512ed47b858602d784d6204 |
2018-10-20 01:47:45-04:00 | clock in - pro bono\n | e6b5f78daa68e3731f82effccb66fd4bd14996bf |
2018-10-20 01:51:36-04:00 | clock out - pro bono\n | 1aff88af5e9688645966ccd15da8e1530205cfea |
2018-10-20 02:03:56-04:00 | clock in - finishing tutorial\n | 53bd7316e579d8582c46af09277b40fbba3a390e |
2018-10-20 02:11:54-04:00 | clock out - converted notebook for README\n | d55b5718a3178ab6161f7e3a148c6561a305cd79 |
2018-10-20 02:14:21-04:00 | had to clock out so notebook examples don't br... | d9ec537b36475b565df6b28d0cab6edc3a89f2da |
2018-10-20 02:18:27-04:00 | fixed for rendering\n | e2f8a2ca212fa9e7568618934da18a0ec7164fa3 |
2018-10-20 02:22:56-04:00 | fixing requiremens that raised a security alert\n | e0e71a05c6c5af1fc5515040ec75f33b71bd3b15 |
2018-10-20 02:51:13-04:00 | fixed requirements, tutorial updates\n | d8d87767005022c9a8e83015d40f6fb736f2b73b |
2018-10-20 02:57:22-04:00 | merging\n | f5585c89612a5fac2d948ee61536fffe276f8949 |
2018-10-20 11:53:00-04:00 | clock in - handling errant messages\n | fa615994ba6b771594d711dea6087cc7ba0348b5 |
2018-10-20 13:16:13-04:00 | clock out - converting to pd.Timestamp\n | ed7aab29e43e7120428816481216198a255de8f4 |
2018-10-20 13:47:56-04:00 | clock in - adding work log\n | 5b398037bf24cd503a7fc88c3b078913fa184f7e |
get_labor
calculates hours worked by differencing commit timestamps and raises an error if clock in and clock out are of different lengths.
Getting time card
get_labor(work, end_date='2018-10-20 02:11:54-04:00')
pay period: 2018-10-19 23:57:48-04:00 -> 2018-10-20 02:11:54-04:00
TimeIn | log in | hash | TimeOut | log out | hash | TimeDelta | |
---|---|---|---|---|---|---|---|
0 | 2018-10-19 23:57:48-04:00 | clock in\n | 5c8f05b57b739ec525291c248ea9200651b49997 | 2018-10-20 00:39:11-04:00 | clock out - work done for the day\n | 0e33fa3d74f663f954b05dd9f30e0128ca7af162 | 00:41:23 |
1 | 2018-10-20 01:06:08-04:00 | clock in - start adding requirements and examp... | dc065b17337b14c2f8e0458de61e6880a338d6ae | 2018-10-20 01:47:01-04:00 | clock out\n | 644ad6ebf4c9015fd512ed47b858602d784d6204 | 00:40:53 |
2 | 2018-10-20 01:47:45-04:00 | clock in - pro bono\n | e6b5f78daa68e3731f82effccb66fd4bd14996bf | 2018-10-20 01:51:36-04:00 | clock out - pro bono\n | 1aff88af5e9688645966ccd15da8e1530205cfea | 00:03:51 |
3 | 2018-10-20 02:03:56-04:00 | clock in - finishing tutorial\n | 53bd7316e579d8582c46af09277b40fbba3a390e | 2018-10-20 02:11:54-04:00 | clock out - converted notebook for README\n | d55b5718a3178ab6161f7e3a148c6561a305cd79 | 00:07:58 |
Handling errant clock in/out messages
If you mistakenly put "clock out" in a message, hourly will interpret the message as a legitimate end time. This will likely raise an error when computing the labor. For example, there is a problematic commit in the this repo's history:
problematic_commit = work[work.hash == 'd9ec537b36475b565df6b28d0cab6edc3a89f2da']
problematic_commit
message | hash | |
---|---|---|
time | ||
2018-10-20 02:14:21-04:00 | had to clock out so notebook examples don't br... | d9ec537b36475b565df6b28d0cab6edc3a89f2da |
When we include this in our labor calculation, we get the following error:
try:
get_labor(work, end_date = '2018-10-20 13:16:13-04:00')
except ValueError as e:
print(e)
pay period: 2018-10-19 23:57:48-04:00 -> 2018-10-20 13:16:13-04:00
In/Out logs do not match
We can skip this errant commit by setting errant_clocks
get_labor(work, end_date = '2018-10-20 13:16:13-04:00',
errant_clocks = ['d9ec537b36475b565df6b28d0cab6edc3a89f2da'])
pay period: 2018-10-19 23:57:48-04:00 -> 2018-10-20 13:16:13-04:00
TimeIn | log in | TimeOut | log out | TimeDelta | |
---|---|---|---|---|---|
0 | 2018-10-19 23:57:48-04:00 | clock in\n | 2018-10-20 00:39:11-04:00 | clock out - work done for the day\n | 00:41:23 |
1 | 2018-10-20 01:06:08-04:00 | clock in - start adding requirements and examp... | 2018-10-20 01:47:01-04:00 | clock out\n | 00:40:53 |
2 | 2018-10-20 01:47:45-04:00 | clock in - pro bono\n | 2018-10-20 01:51:36-04:00 | clock out - pro bono\n | 00:03:51 |
3 | 2018-10-20 02:03:56-04:00 | clock in - finishing tutorial\n | 2018-10-20 02:11:54-04:00 | clock out - converted notebook for README\n | 00:07:58 |
4 | 2018-10-20 11:53:00-04:00 | clock in - handling errant messages\n | 2018-10-20 13:16:13-04:00 | clock out - converting to pd.Timestamp\n | 01:23:13 |
Filtering work session keywords
Use the "ignore" key word to skip any work you don't want to include in your invoices.
labor = get_labor(work,
ignore = 'pro bono',
end_date = '2018-10-20 13:16:13-04:00',
errant_clocks = ['d9ec537b36475b565df6b28d0cab6edc3a89f2da'])
labor
pay period: 2018-10-19 23:57:48-04:00 -> 2018-10-20 13:16:13-04:00
ignoring pro bono
TimeIn | log in | TimeOut | log out | TimeDelta | |
---|---|---|---|---|---|
0 | 2018-10-19 23:57:48-04:00 | clock in\n | 2018-10-20 00:39:11-04:00 | clock out - work done for the day\n | 00:41:23 |
1 | 2018-10-20 01:06:08-04:00 | clock in - start adding requirements and examp... | 2018-10-20 01:47:01-04:00 | clock out\n | 00:40:53 |
3 | 2018-10-20 02:03:56-04:00 | clock in - finishing tutorial\n | 2018-10-20 02:11:54-04:00 | clock out - converted notebook for README\n | 00:07:58 |
4 | 2018-10-20 11:53:00-04:00 | clock in - handling errant messages\n | 2018-10-20 13:16:13-04:00 | clock out - converting to pd.Timestamp\n | 01:23:13 |
Get total earnings
Total earnings can be found using this function. Currency is just a string for printing, but in the future we can add unit conversion.
get_earnings(labor, wage = 30, currency = 'USD')
0 days 02:53:27, 2.890833333333333 hours worked
86.72 USD
86.72
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.