Using Timekeeper class
The example above shows the Timekeeper class in action. You'll notice that the temporal drift is always being corrected and generally stays accurate to within 0.1 seconds. I only need accuracy to within one second for my clock so this should be fine. The two more common techniques are shown below again for comparison.
Using movie frame rate
Using AS3 Timer class
The Timekeeper works by using a very fast internal regulator to update a much slower 'user clock'. Periodic accuracy (isochronism) is achieved by maintaining an accumulator based on the system clock. When the value of the accumulator becomes greater than the tick frequency then a user tick event is produced. Abstracting the timekeeping functions from the periodic mechanism allowed me to add some cool features to the Timekeeper class:
setValue( ms:Number ):void
Get and set the value of time in milliseconds since the Unix epoch. Notice the datatype is Number rather than a Date. This is for reasons of speed, capacity and interoperability with other timekeeping systems. I'll cover this design decision in more detail in a future entry. Conversion to Date is really simple though. If the value of the Timekeeper is ms then you can turn it into a Date like so:
var d = new Date(ms)
setTickDuration( ms:Number ):void
Tick duration is the value in milliseconds that that gets added to the value of the timekeeper every time there is a tick event. The default is one second (e.g. one second per second). Changing the tick duration to one day would run the timekeeper much faster than real time (e.g. one day per second). Changing the tick duration to a negative number will run the timekeeper backwards. Fractional values of a second will work but are not recommended.
setTickFrequency( ms:Number ):void
Tick frequency is the length of time between ticks. The default is one second (e.g. one second per second). Changing the tick frequency to two seconds would run the timekeeper at half real time (e.g. one second per two seconds). The datatype for tick frequency is int rather than Number as all values must be positive and large durations between ticks are impractical.
It is often handy to be able to stop or pause the timekeeper. Tick events are ignored when the Timekeeper is stopped.
Two functions added for convenience.
setRealTimeValue() sets the value of the Timekeeper to "now".
setRealTimeTick() sets the running speed to "real time", i.e. one second per second.