Skip to content

Instantly share code, notes, and snippets.

@alexprengere
Last active August 29, 2015 13:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alexprengere/9526152 to your computer and use it in GitHub Desktop.
Save alexprengere/9526152 to your computer and use it in GitHub Desktop.
Simple converter from pace to reference times for runners.
#!/usr/bin/env python
"""
Simple converter from pace to reference times
for runners.
$ ./run_times_from_pace.py 4:15 -d 1.0
1.00km in 0:04:15 gives you:
1km: 0:04:15 ( 1.00km)
5km: 0:21:15 ( 5.00km)
10km: 0:42:30 (10.00km)
10miles: 1:08:22.950000 (16.09km)
Half-marathon: 1:29:40.500000 (21.10km)
30km: 2:07:30 (30.00km)
Marathon: 2:59:21 (42.20km)
Speed: 14.12 km/h
"""
from datetime import timedelta
from operator import itemgetter
DISTANCES = [
(0.05, '50m'),
(0.1, '100m'),
(1, '1km'),
(5, '5km'),
(10, '10km'),
(16.09, '10miles'),
(20, '20km'),
(21.1, 'Half-marathon'),
(30, '30km'),
(42.2, 'Marathon'),
(50, '50km'),
(100, '100km'),
]
def fmt_minutes(minutes):
"""Nicely format a duration in minutes.
>>> fmt_minutes(30)
'0:30:00'
>>> fmt_minutes(120)
'2:00:00'
>>> fmt_minutes(60 * 48)
'2 days, 0:00:00'
"""
seconds = 60 * minutes
return str(timedelta(seconds=seconds))
def duration_to_minutes(dur):
"""Parse HH:MM:SS date input.
>>> duration_to_minutes('01:00:00')
60.0
>>> duration_to_minutes('00:30:30')
30.5
>>> duration_to_minutes('15:00')
15.0
>>> duration_to_minutes('5')
5.0
"""
dur = dur.split(':')
if len(dur) == 3:
return float(dur[0]) * 60 + float(dur[1]) + float(dur[2]) / 60
if len(dur) == 2:
return float(dur[0]) + float(dur[1]) / 60
return float(dur[0])
def main(minutes, distance, extra_distance=None):
"""Main.
"""
# This is the pace in minutes per km
min_per_km = minutes / distance
print '{0:.2f}km in {1} gives you:\n'.format(distance,
fmt_minutes(minutes))
if extra_distance is None:
distances = DISTANCES
else:
distances = DISTANCES + [(extra_distance, '(*) {0:5.3f}km'.format(extra_distance))]
for d, name in sorted(distances, key=itemgetter(0)):
print '{0:>15}: {1:<15} ({2:5.3f}km)'.format(name,
fmt_minutes(min_per_km * d),
float(d))
print '\n{0:>15}: {1} for 1km'.format('Pace', fmt_minutes(min_per_km))
if min_per_km == 0:
print 'Infinite speed ;)'
else:
print '{0:>15}: {1:.3f} km/h'.format('Speed', 60.0 / min_per_km)
def _test():
"""Run doctests.
"""
import doctest
doctest.testmod()
if __name__ == '__main__':
_test()
import argparse, sys
import os.path as op
from textwrap import dedent
parser = argparse.ArgumentParser(
formatter_class=argparse.RawTextHelpFormatter,
description=dedent("""\
Input the duration needed to run 1km,
this is your pace in minutes per km,
the script will give you reference
times on standard running distances.
"""))
parser.add_argument("duration",
help=dedent("""\
Duration, formatted HH:MM:SS.
Partial durations will be parsed
as MM:SS, then MM.
"""))
parser.add_argument("-d", "--distance",
type=float,
default=1.0,
help=dedent("""\
Distance in km, default is 1.0,
this way the input is the pace
in minutes per km. You can change
it to input a different distance.
"""))
parser.add_argument("-D", "--extra-distance",
type=float,
default=None,
help=dedent("""\
If given, in km, add an extra distance
to the output.
"""))
parser.epilog = dedent("""\
Examples:
./{0} 4:15
./{1} 1:32:00 -d 12.6
./{2} 00:20 -d 0.1
""".format(*(op.basename(sys.argv[0]),) * 3))
args = parser.parse_args()
minutes = duration_to_minutes(args.duration)
main(minutes, args.distance, args.extra_distance)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment