
As a developer fully committed (pun intended, and not the only one) in FOSS side projects, I often lose track of time. It feels like I’ve spent countless hours coding, but how many exactly? Curiosity got the best of me, so I decided to write a Node.js script to find out. Spoiler: I immediately regretted this decision after seeing just how much of my free time was spent coding.
Drafting the plan#
I wanted a script that could calculate my working hours based on my GIT commits. Since I’m an avid believer of the atomic commits conventions, the idea is simple: when I’m working on my side projects, I’m committing. If there’s a gap of more than 3 hours between commits it means I’m probably off doing something else, like eating, sleeping, or watching programming videos (no wait).
Choosing the right package#
There are many GIT libraries for Node.js, but I went with simple-git for its ease of use. It’s a wrapper around GIT commands, making it perfect for this task.
So after installing simple-git, and doing npm init and all of these shenanigans, I was ready to start coding.
The code#
Ok, let’s first get familiarized with simple-git, here is a simple code to fetch the commit log:
const simpleGIT = require('simple-git');
const git = simpleGIT();
async function getCommitLog() {
try {
const log = await git.log();
return log.all;
} catch (error) {
console.error('Error fetching commit log:', error);
}
}
getCommitLog().then(commits => console.log(commits));With the commit log in hand, let’s “apply” our drafted plan into code and calculate the work hours. The idea is to iterate through the commits, and whenever there’s a gap of more than 3 hours between two commits, consider the previous commit as the end of a work session.
So for example, if I start working at 9 AM and commit at 10 AM, then commit again at 3 PM, the script should consider the work session to be from 9 AM to 10 AM, so 1 hour.
async function calculateWorkHours() {
try {
const commits = await getCommitLog();
if (commits.length === 0) {
console.log('No commits found in this repository.');
return;
}
let totalWorkTime = 0;
let currentCommit = commits[0];
const maxInterval = 3 * (60 * 60 * 1000); // 3 hours in milliseconds
for (let i = 1; i < commits.length; i++) {
const nextCommit = commits[i];
const currentCommitTime = new Date(currentCommit.date).getTime();
const nextCommitTime = new Date(nextCommit.date).getTime();
if ((currentCommitTime - nextCommitTime) > maxInterval) {
totalWorkTime += currentCommitTime - new Date(commits[i - 1].date).getTime();
currentCommit = nextCommit;
}
}
totalWorkTime += new Date(currentCommit.date).getTime() - new Date(commits[commits.length - 1].date).getTime();
const totalWorkHours = totalWorkTime / (1000 * 60 * 60);
console.log(`Total work hours: ${totalWorkHours.toFixed(2)} hours`);
} catch (error) {
console.error('Error calculating work hours:', error);
}
}
calculateWorkHours();That’s basically it, but since we’re here, why not squeeze some more information? Not that knowing the total hours isn’t enough, but now I want to know how much time, on average, I am, uh, wasting - uh, I mean, having some quality time with my laptop.
Let’s add that calculation:
async function calculateWorkHours() {
try {
const commits = await getCommitLog();
if (commits.length === 0) {
console.log('No commits found in this repository.');
return;
}
let totalWorkTime = 0;
let currentCommit = commits[0];
const maxInterval = 3 * (60 * 60 * 1000); // 3 hours in milliseconds
for (let i = 1; i < commits.length; i++) {
const nextCommit = commits[i];
const currentCommitTime = new Date(currentCommit.date).getTime();
const nextCommitTime = new Date(nextCommit.date).getTime();
if ((currentCommitTime - nextCommitTime) > maxInterval) {
totalWorkTime += currentCommitTime - new Date(commits[i - 1].date).getTime();
currentCommit = nextCommit;
}
}
totalWorkTime += new Date(currentCommit.date).getTime() - new Date(commits[commits.length - 1].date).getTime();
const totalWorkHours = totalWorkTime / (1000 * 60 * 60);
const firstCommitTime = new Date(commits[commits.length - 1].date).getTime();
const lastCommitTime = new Date(commits[0].date).getTime();
const totalDays = (lastCommitTime - firstCommitTime) / (1000 * 60 * 60 * 24);
const averageHoursPerDay = totalWorkHours / totalDays;
console.log(`Total work hours: ${totalWorkHours.toFixed(2)} hours`);
console.log(`Average hours per day: ${averageHoursPerDay.toFixed(2)} hours`);
} catch (error) {
console.error('Error calculating work hours:', error);
}
}
calculateWorkHours();Let’s put it to practice#
After running the script on my latest side project, which I might write a blog post about soon, I was greeted with the following output:
$ node scripts/calculateWorkHours.js
Total work hours: 98.77 hours
Average hours per day: 3.74 hoursExcuse me, what? 98.77 hours? That’s almost 100 hours spent on a side project in a month. And 3.74 hours per day? I mean, I knew I was spending a lot of time on my side projects, but seeing the numbers was a bit of a shock.
If people ask me, I say I’m quite an active person, after all, I do springboard diving 3 times a week, for a total of 4 hours per week, plus the gym sessions, around a total of 6 hours per week. So, yeah, a total of 10 hours per week, or 1.42 hours per day, not even close to the 3.74 hours per day I’m spending on my side projects.

Caveats#
This script works, but it has some flaws:
- Assumptions on breaks: It assumes any period longer than 3 hours between commits is a break. This might not always be true, but it’s a good enough approximation.
- Commit habits: If you’re someone who forgets to commit frequently, the script’s accuracy plummets.
- Timezone differences: Commits made in different time zones can mess with the calculations.
- Figuring out how much time you’re wasting: This one is a bit subjective, I guess, but in my case, oof, I was not ready for that number.
Conclusion#
Writing this script was enlightening and horrifying all at once. I now have concrete proof of the absurd number of hours I spend on my side projects. If you’re curious (or crazy) enough to “bisect” your programming habits, it can be quite a “fun” exercise.
And remember, while tracking your productivity is great, sometimes ignorance is bliss because after seeing my total hours, I just wanted to curl up and play some of my backlog games to compensate for all that lost free time.
Happy coding, and happy atomic commits!