JLS Time

group jls_time

JLS time representation.

The C standard library includes time.h which is very inconvenient for any precision application. This module defines a much simpler 64-bit fixed point integer for representing time. The value is 34Q30 with the upper 34 bits to represent whole seconds and the lower 30 bits to represent fractional seconds. A value of 2**30 (1 << 30) represents 1 second. This representation gives a resolution of 2 ** -30 (approximately 1 nanosecond) and a range of +/- 2 ** 33 (approximately 272 years). The value is signed to allow for simple arithmetic on the time either as a fixed value or as deltas.

Certain elements may elect to use floating point time given in seconds. The macros JLS_TIME_TO_F64() and JLS_F64_TO_TIME() facilitate converting between the domains. Note that double precision floating point is not able to maintain the same resolution over the time range as the 64-bit representation. JLS_TIME_TO_F32() and JLS_F32_TO_TIME() allow conversion to single precision floating point which has significantly reduce resolution compared to the 34Q30 value.

Defines

JLS_TIME_Q

The number of fractional bits in the 64-bit time representation.

JLS_TIME_MAX

The maximum (positive) time representation.

JLS_TIME_MIN

The minimum (negative) time representation.

JLS_TIME_EPOCH_UNIX_OFFSET_SECONDS

The offset from the standard UNIX (POSIX) epoch.

This offset allows translation between jls time and the standard UNIX (POSIX) epoch of Jan 1, 1970.

The value was computed using python3:

import dateutil.parser
dateutil.parser.parse('2018-01-01T00:00:00Z').timestamp()
JLS chooses a different epoch to advance “zero” by 48 years!

JLS_TIME_SECOND

The fixed-point representation for 1 second.

JLS_FRACT_MASK

The mask for the fractional bits.

JLS_TIME_MILLISECOND

The approximate fixed-point representation for 1 millisecond.

JLS_TIME_MICROSECOND

The approximate fixed-point representation for 1 microsecond.

CAUTION: this value is 0.024% accurate (240 ppm)

JLS_TIME_NANOSECOND

The approximate fixed-point representation for 1 nanosecond.

WARNING: this value is only 6.7% accurate!

JLS_TIME_MINUTE

The fixed-point representation for 1 minute.

JLS_TIME_HOUR

The fixed-point representation for 1 hour.

JLS_TIME_DAY

The fixed-point representation for 1 day.

JLS_TIME_WEEK

The fixed-point representation for 1 week.

JLS_TIME_MONTH

The average fixed-point representation for 1 month (365 day year).

JLS_TIME_YEAR

The approximate fixed-point representation for 1 year (365 days).

JLS_TIME_TO_F64(x)

Convert the 64-bit fixed point time to a double.

Parameters:
  • x – The 64-bit signed fixed point time.

Returns:

The time as a double p. Note that IEEE 747 doubles only have 52 bits of precision, so the result will be truncated for very small deltas.

JLS_TIME_TO_F32(x)

Convert the 64-bit fixed point time to single precision float.

Parameters:
  • x – The 64-bit signed fixed point time.

Returns:

The time as a float p in seconds. Note that IEEE 747 singles only have 23 bits of precision, so the result will likely be truncated.

JLS_TIME_TO_SECONDS(x)

Convert to 32-bit unsigned seconds.

Parameters:
  • x – The 64-bit signed fixed point time.

Returns:

The 64-bit unsigned time in seconds, rounded to nearest.

JLS_TIME_TO_MILLISECONDS(x)

Convert to milliseconds.

Parameters:
  • x – The 64-bit signed fixed point time.

Returns:

The 64-bit signed time in milliseconds, rounded to nearest.

JLS_TIME_TO_MICROSECONDS(x)

Convert to microseconds.

Parameters:
  • x – The 64-bit signed fixed point time.

Returns:

The 64-bit signed time in microseconds, rounded to nearest.

JLS_TIME_TO_NANOSECONDS(x)

Convert to nanoseconds.

Parameters:
  • x – The 64-bit signed fixed point time.

Returns:

The 64-bit signed time in nanoseconds, rounded to nearest.

JLS_SECONDS_TO_TIME(x)

Convert to 64-bit signed fixed point time.

Parameters:
  • x – he 32-bit unsigned time in seconds.

Returns:

The 64-bit signed fixed point time.

JLS_MILLISECONDS_TO_TIME(x)

Convert to 64-bit signed fixed point time.

Parameters:
  • x – The 32-bit unsigned time in milliseconds.

Returns:

The 64-bit signed fixed point time.

JLS_MICROSECONDS_TO_TIME(x)

Convert to 64-bit signed fixed point time.

Parameters:
  • x – The 32-bit unsigned time in microseconds.

Returns:

The 64-bit signed fixed point time.

JLS_NANOSECONDS_TO_TIME(x)

Convert to 64-bit signed fixed point time.

Parameters:
  • x – The 32-bit unsigned time in microseconds.

Returns:

The 64-bit signed fixed point time.

Functions

static inline int64_t JLS_F64_TO_TIME(double x)

Convert the double precision time to 64-bit fixed point time.

Parameters:

x – The double-precision floating point time in seconds.

Returns:

The time as a 34Q30.

static inline int64_t JLS_F32_TO_TIME(float x)

Convert the single precision float time to 64-bit fixed point time.

Parameters:

x – The single-precision floating point time in seconds.

Returns:

The time as a 34Q30.

static inline int64_t JLS_TIME_TO_COUNTER(int64_t x, uint64_t z)

Convert to counter ticks, rounded to nearest.

Parameters:
  • x – The 64-bit signed fixed point time.

  • z – The counter frequency in Hz.

Returns:

The 64-bit time in counter ticks.

static inline int64_t JLS_TIME_TO_COUNTER_RZERO(int64_t x, uint64_t z)

Convert to counter ticks, rounded towards zero.

Parameters:
  • x – The 64-bit signed fixed point time.

  • z – The counter frequency in Hz.

Returns:

The 64-bit time in counter ticks.

static inline int64_t JLS_TIME_TO_COUNTER_RINF(int64_t x, uint64_t z)

Convert to counter ticks, rounded towards infinity.

Parameters:
  • x – The 64-bit signed fixed point time.

  • z – The counter frequency in Hz.

Returns:

The 64-bit time in counter ticks.

static inline int64_t JLS_COUNTER_TO_TIME(uint64_t x, uint64_t z)

Convert a counter to 64-bit signed fixed point time.

Parameters:
  • x – The counter value in ticks.

  • z – The counter frequency in Hz.

Returns:

The 64-bit signed fixed point time.

static inline int64_t JLS_TIME_ABS(int64_t t)

Compute the absolute value of a time.

Parameters:

t – The time.

Returns:

The absolute value of t.

int64_t jls_now(void)

Get the UTC time as a 34Q30 fixed point number.

At power-on, the time will start from 0 unless the system has a real-time clock. When the current time first synchronizes to an external host, it may have a large skip.

Be sure to verify your time for each platform using python:

 python
 import datetime
 import dateutil.parser
 epoch = dateutil.parser.parse('2018-01-01T00:00:00Z').timestamp()
 datetime.datetime.fromtimestamp((my_time >> 30) + epoch)

Returns:

The current time. This value is not guaranteed to be monotonic. The device may synchronize to external clocks which can cause discontinuous jumps, both backwards and forwards.

struct jls_time_counter_s jls_time_counter(void)

Get the monotonic platform counter.

The platform implementation may select an appropriate source and frequency. The JLS library assumes a nominal frequency of at least 1000 Hz, but we frequencies in the 1 MHz to 100 MHz range to enable profiling. The frequency should not exceed 10 GHz to prevent rollover.

The counter must be monotonic. If the underlying hardware is less than the full 64 bits, then the platform must unwrap and extend the hardware value to 64-bit.

The JLS authors recommend this counter starts at 0 when the system powers up.

Returns:

The monotonic platform counter.

static inline int64_t jls_time_rel(void)

Get the monotonic platform time as a 34Q30 fixed point number.

Returns:

The monotonic platform time based upon the jls_time_counter(). The platform time has no guaranteed relationship with UTC or wall-clock calendar time. This time has both offset and scale errors relative to UTC.

struct jls_time_counter_s
#include <time.h>

The platform counter structure.

Public Members

uint64_t value

The counter value.

uint64_t frequency

The approximate counter frequency.