There's lots of different kinds of time:
And then the clocks can run faster or slower or jump backwards or forwards because of
And how these are dealt with depends in turn on:
So please can somebody tell me, for my specific use case, the safest and most reliable way to measure a short interval? Here is what I am doing:
I'm making a game in Python (3.7.x) and I need to keep track of how long it has been since certain events. For example, how long the player has been holding a button, or how long since an enemy has spotted the player, or how long since a level was loaded. Timescales should be accurate to the millisecond (nanoseconds are overkill).
You play the game late at night. In your timezone, on that night, the clocks go forward an hour at 2am for DST, so the minutes go: 1:58, 1:59, 2:00, 3:01, 3:02. Every time-related variable in the game suddenly has an extra hour added to it -- it thinks you'd been holding down that button for an hour and 2 seconds instead of just 2 seconds. Catastrophe ensues.
The same, but the IERS decides to insert or subtract a leap second sometime that day. You play through the transition, and all time variables get an extra second added or subtracted. Catastrophe ensues.
You play the game on a train or plane and catastrophe ensues when you cross a timezone boundary and/or the International Date Line.
The game works correctly in the above scenarios on some hardware and operating systems, but not others. I.e. it breaks on Linux but not Window, or vice versa.
And I can't really write tests for these since the problematic events come around so rarely. I need to get it right the first time. So, what time-related function do I need to use? I know there's plain old time.time()
, but also a bewildering array of other options like
time.clock()
time.perf_counter()
time.process_time()
time.monotonic()
From reading the documentation it seems like time.monotonic()
is the one I want. But if reading about all the details of timekeeping has taught me anything, it's that these things are never quite what they seem. Once upon a time, I thought I knew what a "second" was. Now I'm not so sure.
So, how do I make sure my game clocks work properly?
The specification of time module is the best place to look for details about each of those.
There, you can easily see that:
time.clock()
is deprecated and should be replaced with other functionstime.process_time()
counts only CPU time spent by your process, so it is not suitable for measuring wall clock time (which is what you need)time.perf_counter()
has the same problem as time.process_time()
time.time()
is just about right, but it will give bad timings if user modifies the current timetime.monotonic()
- this seems to be the safest bet for measuring time intervals - note that this does not give you current time at all, but it gives you a correct difference between two time pointsAs for the nanoseconds versions, you should use those only if you need nanoseconds.