Skip to content

Instantly share code, notes, and snippets.

@bessarabov
Last active September 2, 2025 01:50
Show Gist options
  • Select an option

  • Save bessarabov/674ea13c77fc8128f24b5e3f53b7f094 to your computer and use it in GitHub Desktop.

Select an option

Save bessarabov/674ea13c77fc8128f24b5e3f53b7f094 to your computer and use it in GitHub Desktop.
One-liner to generate data shown in post 'At what time of day does famous programmers work?' — https://ivan.bessarabov.com/blog/famous-programmers-work-time
git log --author="Linus Torvalds" --date=iso | perl -nalE 'if (/^Date:\s+[\d-]{10}\s(\d{2})/) { say $1+0 }' | sort | uniq -c|perl -MList::Util=max -nalE '$h{$F[1]} = $F[0]; }{ $m = max values %h; foreach (0..23) { $h{$_} = 0 if not exists $h{$_} } foreach (sort {$a <=> $b } keys %h) { say sprintf "%02d - %4d %s", $_, $h{$_}, "*"x ($h{$_} / $m * 50); }'
@bohwaz

bohwaz commented Jul 16, 2019

Copy link
Copy Markdown

This isn't really useful unless it does account for local timezone used when committing? As you can operate from different timezones.

Result from drh on SQLite repo:

00 -  724 *********************************
01 -  667 *******************************
02 -  515 ***********************
03 -  325 ***************
04 -  137 ******
05 -   37 *
06 -   18 
07 -   19 
08 -   16 
09 -   42 *
10 -  139 ******
11 -  415 *******************
12 -  711 *********************************
13 - 1029 ***********************************************
14 - 1051 ************************************************
15 - 1025 ***********************************************
16 -  891 *****************************************
17 -  965 ********************************************
18 - 1074 **************************************************
19 -  893 *****************************************
20 -  876 ****************************************
21 -  563 **************************
22 -  489 **********************
23 -  608 ****************************

@bessarabov

Copy link
Copy Markdown
Author

Thank you for the graph!

The script uses the time the author saw on his wall clock when doing the commit. I can't imagine better time to use for such graphs.

@bohwaz

bohwaz commented Jul 16, 2019

Copy link
Copy Markdown

Interesting, I thought it was a UTC timestamp. Thanks for the clarification!

@bfontaine

bfontaine commented Jul 18, 2019

Copy link
Copy Markdown

You don’t need to use Perl just to get the hours of each commit; Git can do it for you:

git log --author="Linus Torvalds" --format="%ad" --date="format:%H"

Edit: just for fun, a much shorter (and slightly faster) oneliner:

git log --author="Linus Torvalds" --format="%ad" --date="format:%H"|awk '{n=$1+0;if(H[n]++>max)max=H[n]}END{for(i=0;i<24;i++){printf"%02d -%5d ",i,H[i];for(n=0;n<H[i]/max*50;n++){printf "*"}print""}}'

@bessarabov

Copy link
Copy Markdown
Author

@bfontaine, thank you! In my second investigation (https://ivan.bessarabov.com/blog/famous-programmers-work-time-part-2-workweek-vs-weekend) i used more of git command:

bessarabov@server:/tmp/linux$ git log --author="Linus Torvalds" --format="%H %ai" |head -3
fec88ab0af9706b2201e5daf377c5031c62d11f7 2019-07-14 19:42:11 -0700
fa6e951a2a440babd7a7310d0f4713e618061767 2019-07-14 19:29:04 -0700
a318423b61e8c67aa5c0a428540c58439a20baac 2019-07-14 17:24:12 -0700

I output not only the hour to simplify the debug process.

bessarabov@server:/tmp/linux$ git log --author="Linus Torvalds" --format="%ad" --date="format:%H"|head -3
19
19
17

ghost commented Jul 18, 2019

Copy link
Copy Markdown

As a git alias:

[alias]
  times = "!git log --author=\"$(git config user.name)\" --date=iso \
      | perl -nalE 'if (/^Date:\\s+[\\d-]{10}\\s(\\d{2})/) { say $1+0 }' \
      | sort \
      | uniq -c \
      | perl -MList::Util=max -nalE '$h{$F[1]} = $F[0]; }{ $m = max values %h; foreach (0..23) { $h{$_} = 0 if not exists $h{$_} } foreach (sort {$a <=> $b } keys %h) { say sprintf \"%02d - %4d %s\", $_, $h{$_}, \"*\"x ($h{$_} / $m * 50); }'"

The changes needed are to escape the backslashes in the first perl command as well as the double quotes in the second one. I also multi-lined it, and lastly I replaced the hardcoded name with getting the name from the gitconfig since if it's in an alias, it should probably default to you. I believe those are all of the changes I made. Probably possible to pass in a name as well

@daixiang0

Copy link
Copy Markdown

also can specify repo path then you can run anywhere:

repo_dir=/path/to/repo
username="Linus Torvalds"
git --git-dir=$repo_dir/.git log --author="$username" --date=iso | perl -nalE 'if (/^Date:\s+[\d-]{10}\s(\d{2})/) { say $1+0 }' | sort | uniq -c|perl -MList::Util=max -nalE '$h{$F[1]} = $F[0]; }{ $m = max values %h; foreach (0..23) { $h{$_} = 0 if not exists $h{$_} } foreach (sort {$a <=> $b } keys %h) { say sprintf "%02d - %4d %s", $_, $h{$_}, "*"x ($h{$_} / $m * 50); }'

@azl397985856

Copy link
Copy Markdown

I got an error with:

zsh: no matches found: {} = ; }{  = max values %h; foreach (0..23) { {tree=ls -R | grep :$ | sed -e s/:$// -e s/[^-][^/]*//--/g -e s/^/
zsh: no matches found: /} = 0 if not exists {tree=ls -R | grep :$ | sed -e s/:$// -e s/[^-][^/]*//--/g -e s/^/
zsh: no matches found: /} } foreach (sort { <=>  } keys %h) { say sprintf "%02d - %4d %s", tree=ls -R | grep :$ | sed -e s/:$// -e s/[^-][^/]*//--/g -e s/^/
zsh: no matches found: /, {tree=ls -R | grep :$ | sed -e s/:$// -e s/[^-][^/]*//--/g -e s/^/
zsh: no matches found: /}, "*"x ({tree=ls -R | grep :$ | sed -e s/:$// -e s/[^-][^/]*//--/g -e s/^/
zsh: no such file or directory: /} /  * 50); }

am I wrong?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment