Module time

A runtime optimized module to compare and do simple arithmetics with fixed point time values (which are called fts in here).

Also implements functions to retrieve time from various system clocks (monotonic, monotoniccoarse, realtime, realtimecoarse, boottime ...).

Encode:

Don't store a numerical constant in an fts encoded time. Use the functions provided here!

To convert real world units to an fts, you can use the following functions: time.s(seconds), time.ms(milliseconds), time.us(microseconds).

You can calculate an fts encoded time of 3 s with time.s(3).

Special values: 0 can be used for a zero time and time.huge can be used for the longest possible time.

Beware of float encoding precision, though. For instance, take 2.1s: 2.1 cannot be encoded with full precision, so time.s(2.1) would be slightly inaccurate. (For small values (under 10 secs) the error will be ±1µs, for values below a minute the error will be below ±2µs, for values below an hour the error will be ±100µs.)

When full precision is necessary, use time.s(2) + time.ms(100) or time.s(2) + time.us(100000) instead.

(For more information about floating-point-representation see: https://stackoverflow.com/questions/3448777/how-to-represent-0-1-in-floating-point-arithmetic-and-decimal)

Decode:

You can get the number of seconds in an fts encoded time with time.to_s(time_fts).

You can get the number of milliseconds in an fts encoded time with time.to_ms(time_fts).

You can get the number of microseconds in an fts encoded time with time.to_us(time_fts).

Please be aware, that time.to_number is the same as a time.to_s with a precision of four decimal places.

Supported calculations:

You can add and subtract all fts encoded times, without any problems.

You can multiply or divide fts encoded times by numerical constants. So if you need the half of a time, time_fts/2 is correct.

A division of two fts encoded times would give you a number. (e.g., time.s(2.5)/time.s(0.5) equals 5).

The functions math.abs(), math.min(), math.max() and math.huge will work as expected.

Comparisons (>, >=, ==, <, <= and ~=) of two fts encoded times work as expected.

If you want a duration form a given time_fts to now, time.since(time_fts) as a shortcut (or simply use fts.now - time_fts) will return an fts encoded time. If you need milliseconds use time.to_ms(time.since(time_fts)).

Unsupported calculations:

Don't add a numerical constant to an fts time (in the best case, the numerical constant is interpreted as µs).

Don't multiply two fts_encoded times (the position of the comma is wrong).

But please be aware that all other not explicitly supported math on fts encoded times (math.xxx()) won't work as expected. (If you really, really need that, you have to shift the position of the comma yourself!)

Background: Numbers in Lua are double float which have a mantissa (precision) of 53 bit (plus sign + exponent) We won't use the exponent here.

So we can store 2^53 = 9.0072E15 different values. If we use the lower 6 digits for µs, we can store up to 9.0072E9 seconds.

A year has 365.25243600 = 3.15576E7 s, so we can store up to 285 years (9.0072E9/3.15576E7) with µs precision.

The module has been tested with the fixed point comma at 10^6 (other values might work, but are not really tested).

Recommendations: If the name of a variable implies a time (now, when, until, xxxdeadline, xxxtime, getElapsedTimeSinceBoot, lastxxxtimexxx, ...) we assume this value to be a time (fts encoded).

Other objects which are times (like last_tap, tap_interval_override, ...) shall be renamed to something like last_tap_time (so to make it clear that they are fts encoded).

All other time variables (a handful) get the appropriate suffix _ms, _us, _s (_m, _h, _d) denoting their status as plain Lua numbers and their resolution.

Usage:

    local time = require("ui/time")
    
    local start_time = time.now()
    -- Do some stuff.
    -- You can add and subtract `fts times` objects.
    local duration = time.now() - start.fts
    -- And convert that object to various more human-readable formats, e.g.,
    print(string.format("Stuff took %.3fms", time.to_ms(duration)))
    
    local offset = time.s(100)
    print(string.format("Stuff plus 100s took %.3fms", time.to_ms(duration + offset)))
    

Functions

s (seconds) Creates a time (fts) from a number in seconds
ms (msec) Creates a time (fts) from a number in milliseconds
us (usec) Creates a time (fts) from a number in microseconds
timeval (tv) Creates a time (fts) from a structure similar to timeval
to_number (time_fts) Converts an fts time to a Lua (decimal) number (sec.usecs) (accurate to the ms, rounded to 4 decimal places)
to_s (time_fts) Converts an fts to a Lua (int) number (resolution: 1µs)
to_ms (time_fts) Converts a fts to a Lua (int) number (resolution: 1ms, rounded).
to_us (time_fts) Converts an fts to a Lua (int) number (resolution: 1µs, rounded)
since (start_time) Compare a past MONOTONIC fts time to now, returning the elapsed time between the two.
split_s_us (time_fts) Splits an fts to seconds and microseconds.
realtime () Returns an fts time based on the current wall clock time.
monotonic () Returns an fts time based on the current value from the system's MONOTONIC clock source.
monotonic_coarse () Ditto, but w/ CLOCKMONOTONICCOARSE if it's available and has a 1ms resolution or better (uses CLOCK_MONOTONIC otherwise).
boottime () Ditto, but w/ CLOCK_BOOTTIME (will return an fts time set to 0, 0 if the clock source is unsupported, as it's 2.6.39+) Only use it if you know it's going to be supported, otherwise, prefer the four following aliases.
format_time (time_fts) Converts an fts time to a string (seconds with 6 decimal places)

Fields

huge Sometimes we need a very large time
now Alias for monotonic_coarse.


Functions

s (seconds)
Creates a time (fts) from a number in seconds

Parameters:

  • seconds
ms (msec)
Creates a time (fts) from a number in milliseconds

Parameters:

  • msec
us (usec)
Creates a time (fts) from a number in microseconds

Parameters:

  • usec
timeval (tv)
Creates a time (fts) from a structure similar to timeval

Parameters:

  • tv
to_number (time_fts)
Converts an fts time to a Lua (decimal) number (sec.usecs) (accurate to the ms, rounded to 4 decimal places)

Parameters:

  • time_fts Round to 4 decimal places
to_s (time_fts)
Converts an fts to a Lua (int) number (resolution: 1µs)

Parameters:

  • time_fts Time in seconds with µs precision (without decimal places)
to_ms (time_fts)
Converts a fts to a Lua (int) number (resolution: 1ms, rounded).

(Mainly useful when computing a time lapse for benchmarking purposes).

Parameters:

  • time_fts Time in milliseconds ms (without decimal places)
to_us (time_fts)
Converts an fts to a Lua (int) number (resolution: 1µs, rounded)

Parameters:

  • time_fts Time in microseconds µs (without decimal places)
since (start_time)
Compare a past MONOTONIC fts time to now, returning the elapsed time between the two. (sec.usecs variant)

Returns a Lua (decimal) number (sec.usecs, with decimal places) (accurate to the µs)

Parameters:

  • start_time Time difference
split_s_us (time_fts)
Splits an fts to seconds and microseconds. If argument is nil, returns nil,nil.

Parameters:

  • time_fts
realtime ()
Returns an fts time based on the current wall clock time. (e.g., gettimeofday / clockgettime(CLOCKREALTIME).

This is a simple wrapper around clockgettime(CLOCKREALTIME) to get all the niceties of a time. If you don't need sub-second precision, prefer os.time(). Which means that, yes, this is a fancier POSIX Epoch ;).

Returns:

    fts fixed point time

Usage:

    local time = require("ui/time")
    local fts_start = time.realtime()
    -- Do some stuff.
    -- You can add and substract fts times
    local fts_duration = time.realtime() - fts_start
monotonic ()
Returns an fts time based on the current value from the system's MONOTONIC clock source. (e.g., clockgettime(CLOCKMONOTONIC).)

POSIX guarantees that this clock source will never go backwards (but it may return the same value multiple times). On Linux, this will not account for time spent with the device in suspend (unlike CLOCK_BOOTTIME).

Returns:

    fts fixed point time
monotonic_coarse ()
Ditto, but w/ CLOCKMONOTONICCOARSE if it's available and has a 1ms resolution or better (uses CLOCK_MONOTONIC otherwise).
boottime ()
Ditto, but w/ CLOCK_BOOTTIME (will return an fts time set to 0, 0 if the clock source is unsupported, as it's 2.6.39+) Only use it if you know it's going to be supported, otherwise, prefer the four following aliases.
format_time (time_fts)
Converts an fts time to a string (seconds with 6 decimal places)

Parameters:

  • time_fts

Fields

huge
Sometimes we need a very large time
now
Alias for monotonic_coarse.

The assumption being anything that requires accurate timestamps expects a monotonic clock source. This is certainly true for KOReader's UI scheduling.

generated by LDoc 1.5.0 Last updated 2024-03-18 16:45:36