Source control, version control, revision control systems, call them what you like, but to the professional programmer, they are everything. I would argue they are the most important tool of any programmer. There are lots to choose from, and this article from Codice Software has a history of them, leading up to their latest and greatest, Plastic SCM. I’ve used Perforce for a long time, but it can’t hurt to spend a bit of time reading up on modern SCM systems to see what’s new!
Anyway, I digress! The pattern of my blog postings seems to have become cyclic over the months, waxing and waning as I get busier at work with whatever project I’m coding. As you might guess from the lack of posts in the last 4 months, the project I’ve just completed has taken up a large amount of my time. Unless you keep a detailed diary and work log, remembering out how much time you’ve spent on a project, over and above a normal working week, isn’t easy. However, it’s something you can work out from the logs of your source control system.
To that end, I present my p4-overtime script:
#!/usr/bin/python
import sys
import datetime
# Assume a full day if a weekend is worked
HOURS_PER_WEEKEND_DAY = 7.5
# Last working hour is 5pm, so anything after 6pm gets a +1 hour
AFTER_WORK_HOUR = 17
AFTER_WORK_MINS = 0
# Useful for printing out weekday numbers
weekdays = ['Mon','Tue','Wed','Thur','Fri','Sat','Sun']
days = {}
# Read the output from the "p4 changes -t -i" command. Each line is formatted like:
# Change 17235 on 2009/03/09 16:05:55 by slonghu@LongSteve 'Bunch of work on the ship deplo'
# Change NNNNN on YYYY/MM/DD HH:MM:SS by USERNAME@CLIENT.. 'Truncated comment text.........'
# Where you have some boiler plate text, a changelist number, date, time, username@client and comment text
for line in sys.stdin:
change = line.split (' ')
changelist = change [1]
datesplit = change [3].split ('/')
timesplit = change [4].split (':')
# Get the time and the day of the change
time = datetime.time (int (timesplit [0]), int (timesplit [1]), int (timesplit [2]))
day = datetime.date (int (datesplit [0]), int (datesplit [1]), int (datesplit [2]))
# Save the day of the week number
weekday = day.weekday ();
# Save the delta time between our last work hour and the actual changelist time
sixpm = datetime.time (AFTER_WORK_HOUR, AFTER_WORK_MINS)
delta = time.hour - sixpm.hour
# -ve delta means it was before 5pm
# 0 delta means between 5pm and 6pm
# +ve delta means after 6pm, translating to extra hours worked.
# store the data for the day. For any one day, we just store the
# changelist data that has the highest delta value, that'll be the
# last one on that day.
new_day = (weekday, delta, time, changelist)
if days.has_key (str (day)):
prev_delta = days [str (day)] [1]
if delta > prev_delta:
days [str (day)] = new_day
else:
days [str (day)] = new_day
# counters for the weekend days and evening hours
weekends = 0
eveninghours = 0
for day in days:
# add a day for each weekend worked
weekday = days [day][0]
if weekday == 5 or weekday == 6:
weekends = weekends + 1
# accumulate the +ve hours
delta = days [day][1]
if delta < 0: delta = 0 eveninghours = eveninghours + delta #if delta > 0:
# print day + " " + str (days [day])
print "Weekend hours: " + str (weekends * HOURS_PER_WEEKEND_DAY) + " (" + str (weekends) +
" days * " + str (HOURS_PER_WEEKEND_DAY)+" hours)"
print "Evening hours: " + str (eveninghours)
print "Total Extra hours: " + str (eveninghours + weekends * HOURS_PER_WEEKEND_DAY)
You use it by piping the output of the “p4 changes -t -i” command through the script. It’s also handy to pipe the output from p4 changes through grep for a particular username first, so something like:
bash>p4 changes -t -i //depot/games/Game/... | grep "username" | p4-overtime
Basically, the script goes through all the commits in the input list. For each weekend that is worked (ie. some code was submitted on a Saturday or Sunday) it totals up 7.5 hours. For each weekday, if the last commit of the day is after 6pm it adds 1 hour to the accumulated total. If the last commit is after 7pm, 2 hours get added, etc, up till midnight when you get an extra 6 hours. It falls down after midnight, but (luckily) in my case this hasn’t been a problem. I’m pretty sure I’ve not been at the office, or even working from home past midnight. Sometimes I do get up early in the morning, and that’s not caught by the script either, but all told, I think it works out evenly in the end. Sometimes I know I only worked a couple of hours one Saturday morning for example, then other times, I’m sure I spent all day, 9am till 9pm…
I’m not going to offer actual numbers for my own projects, at least not yet. Suffice to say that they are very eye opening! As a programmer, it’s very easy to get so absorbed in what you do, that stopping and leaving it till the next day can be very hard. I have this mental block where I find it really hard to leave at the end of the day without some sort of block closure on the feature I’m coding. Even though I know that as the hours pile up, my coding definitely does not improve. Debugging is another area that highlights this too. How many times have you been hunting a nasty bug, forgot the time and notice it’s late. You leave the office frustrated you couldn’t solve the problem. Then in the morning, you boot up your computer and have it fixed within 10 minutes, probably before the first coffee of the day is even cold!

Thanks for the fair comment James. I’ve edited the post a bit so as not to make it look like you guys were ragging on Perforce, which you weren’t of course. I’ve used Perforce for a number of years and it supports our development style very well. When developing our games, we really only use short lived side branches to support the development of risky features that may take a few weeks and might disrupt the codebase; so they’re best kept off the trunk. My experience doing this is that it’s quick and easy, and the tools support you well, but it is a very simple use case I admit. I will have to take a look at Plastic sometime and see what it offers, the 15 user community license is quite generous I think.
Hello, nice blog post. Just a quick comment where you said the scm time-line blog (referenced above) says that Perforce branching is bad. Actually, the blog makes references to how branches are implemented in Perforce, but never says that “branches are bad”. One of the goals for that time-line blog was to not be derogatory or negative towards any one vendor. Much of what is written is based on direct experience and information shared with us from our customers (we have several that have migrated from Perforce to Plastic). What I can say is that Pablo (the author of the post), gives some credit towards Perforce (and several other SCM tools) such as “…it is rock solid, mature, and well established.” We certainly understand and appreciate the loyal following Perforce (and other SCM tools) have. Without your support, many of these vendors would have perished long ago. Clearly you have a passion for SCM and for Perforce and that should continue.