1.. _timeutil_api:
2
3Time Utilities
4##############
5
6Overview
7********
8
9:ref:`kernel_timing_uptime` in Zephyr is based on the a tick counter.  With
10the default :kconfig:option:`CONFIG_TICKLESS_KERNEL` this counter advances at a
11nominally constant rate from zero at the instant the system started. The POSIX
12equivalent to this counter is something like ``CLOCK_MONOTONIC`` or, in Linux,
13``CLOCK_MONOTONIC_RAW``.  :c:func:`k_uptime_get()` provides a millisecond
14representation of this time.
15
16Applications often need to correlate the Zephyr internal time with external
17time scales used in daily life, such as local time or Coordinated Universal
18Time.  These systems interpret time in different ways and may have
19discontinuities due to `leap seconds <https://what-if.xkcd.com/26/>`__ and
20local time offsets like daylight saving time.
21
22Because of these discontinuities, as well as significant inaccuracies in the
23clocks underlying the cycle counter, the offset between time estimated from
24the Zephyr clock and the actual time in a "real" civil time scale is not
25constant and can vary widely over the runtime of a Zephyr application.
26
27The time utilities API supports:
28
29* :ref:`converting between time representations <timeutil_repr>`
30* :ref:`synchronizing and aligning time scales <timeutil_sync>`
31* :ref:`comparing, adding, and subtracting representations <timeutil_manip>`
32
33For terminology and concepts that support these functions see
34:ref:`timeutil_concepts`.
35
36Time Utility APIs
37*****************
38
39.. _timeutil_repr:
40
41Representation Transformation
42=============================
43
44Time scale instants can be represented in multiple ways including:
45
46* Seconds since an epoch. POSIX representations of time in this form include
47  ``time_t`` and ``struct timespec``, which are generally interpreted as a
48  representation of `"UNIX Time"
49  <https://tools.ietf.org/html/rfc8536#section-2>`__.
50
51* Calendar time as a year, month, day, hour, minutes, and seconds relative to
52  an epoch. POSIX representations of time in this form include ``struct tm``.
53
54Keep in mind that these are simply time representations that must be
55interpreted relative to a time scale which may be local time, UTC, or some
56other continuous or discontinuous scale.
57
58Some necessary transformations are available in standard C library
59routines. For example, ``time_t`` measuring seconds since the POSIX EPOCH is
60converted to ``struct tm`` representing calendar time with `gmtime()
61<https://pubs.opengroup.org/onlinepubs/9699919799/functions/gmtime.html>`__.
62Sub-second timestamps like ``struct timespec`` can also use this to produce
63the calendar time representation and deal with sub-second offsets separately.
64
65The inverse transformation is not standardized: APIs like ``mktime()`` expect
66information about time zones.  Zephyr provides this transformation with
67:c:func:`timeutil_timegm` and :c:func:`timeutil_timegm64`.
68
69To convert between ``struct timespec`` and ``k_timeout_t`` durations,
70use :c:func:`timespec_to_timeout` and :c:func:`timespec_from_timeout`.
71
72.. code-block:: c
73
74    k_timeout_t to;
75    struct timespec ts;
76
77    timespec_from_timeout(K_FOREVER, &ts);
78    to = timespec_to_timeout(&ts); /* to == K_FOREVER */
79
80    timespec_from_timeout(K_MSEC(100), &ts);
81    to = timespec_to_timeout(&ts); /* to == K_MSEC(100) */
82
83.. doxygengroup:: timeutil_repr_apis
84
85.. _timeutil_sync:
86
87Time Scale Synchronization
88==========================
89
90There are several factors that affect synchronizing time scales:
91
92* The rate of discrete instant representation change.  For example Zephyr
93  uptime is tracked in ticks which advance at events that nominally occur at
94  :kconfig:option:`CONFIG_SYS_CLOCK_TICKS_PER_SEC` Hertz, while an external time
95  source may provide data in whole or fractional seconds (e.g. microseconds).
96* The absolute offset required to align the two scales at a single instant.
97* The relative error between observable instants in each scale, required to
98  align multiple instants consistently.  For example a reference clock that's
99  conditioned by a 1-pulse-per-second GPS signal will be much more accurate
100  than a Zephyr system clock driven by a RC oscillator with a +/- 250 ppm
101  error.
102
103Synchronization or alignment between time scales is done with a multi-step
104process:
105
106* An instant in a time scale is represented by an (unsigned) 64-bit integer,
107  assumed to advance at a fixed nominal rate.
108* :c:struct:`timeutil_sync_config` records the nominal rates of a reference
109  time scale/source (e.g. TAI) and a local time source
110  (e.g. :c:func:`k_uptime_ticks`).
111* :c:struct:`timeutil_sync_instant` records the representation of a single
112  instant in both the reference and local time scales.
113* :c:struct:`timeutil_sync_state` provides storage for an initial instant, a
114  recently received second observation, and a skew that can adjust for
115  relative errors in the actual rate of each time scale.
116* :c:func:`timeutil_sync_ref_from_local()` and
117  :c:func:`timeutil_sync_local_from_ref()` convert instants in one time scale
118  to another taking into account skew that can be estimated from the two
119  instances stored in the state structure by
120  :c:func:`timeutil_sync_estimate_skew`.
121
122.. doxygengroup:: timeutil_sync_apis
123
124.. _timeutil_manip:
125
126``timespec`` Manipulation
127=========================
128
129Checking the validity of a ``timespec`` can be done with :c:func:`timespec_is_valid`.
130
131.. code-block:: c
132
133    struct timespec ts = {
134        .tv_sec = 0,
135        .tv_nsec = -1, /* out of range! */
136    };
137
138    if (!timespec_is_valid(&ts)) {
139        /* error-handing code */
140    }
141
142In some cases, invalid ``timespec`` objects may be re-normalized using
143:c:func:`timespec_normalize`.
144
145.. code-block:: c
146
147    if (!timespec_normalize(&ts)) {
148        /* error-handling code */
149    }
150
151    /* ts should be normalized */
152    __ASSERT(timespec_is_valid(&ts) == true, "expected normalized timespec");
153
154It is possible to compare two ``timespec`` objects for equality using :c:func:`timespec_equal`.
155
156.. code-block:: c
157
158    if (timespec_equal(then, now)) {
159        /* time is up! */
160    }
161
162It is possible to compare and fully order (valid) ``timespec`` objects using
163:c:func:`timespec_compare`.
164
165.. code-block:: c
166
167    int cmp = timespec_compare(a, b);
168
169    switch (cmp) {
170    case 0:
171        /* a == b */
172        break;
173    case -1:
174        /* a < b */
175        break;
176    case +1:
177        /* a > b */
178        break;
179    }
180
181It is possible to add, subtract, and negate ``timespec`` objects using
182:c:func:`timespec_add`, :c:func:`timespec_sub`, and :c:func:`timespec_negate`,
183respectively. Like :c:func:`timespec_normalize`, these functions will output
184a normalized ``timespec`` when doing so would not result in overflow.
185On success, these functions return ``true``. If overflow would occur, the
186functions return ``false``.
187
188.. code-block:: c
189
190    /* a += b */
191    if (!timespec_add(&a, &b)) {
192        /* overflow */
193    }
194
195    /* a -= b */
196    if (!timespec_sub(&a, &b)) {
197        /* overflow */
198    }
199
200    /* a = -a */
201    if (!timespec_negate(&a)) {
202        /* overflow */
203    }
204
205.. doxygengroup:: timeutil_timespec_apis
206
207
208.. _timeutil_concepts:
209
210Concepts Underlying Time Support in Zephyr
211******************************************
212
213Terms from `ISO/TC 154/WG 5 N0038
214<https://www.loc.gov/standards/datetime/iso-tc154-wg5_n0038_iso_wd_8601-1_2016-02-16.pdf>`__
215(ISO/WD 8601-1) and elsewhere:
216
217* A *time axis* is a representation of time as an ordered sequence of
218  instants.
219* A *time scale* is a way of representing an instant relative to an origin
220  that serves as the epoch.
221* A time scale is *monotonic* (increasing) if the representation of successive
222  time instants never decreases in value.
223* A time scale is *continuous* if the representation has no abrupt changes in
224  value, e.g. jumping forward or back when going between successive instants.
225* `Civil time <https://en.wikipedia.org/wiki/Civil_time>`__ generally refers
226  to time scales that legally defined by civil authorities, like local
227  governments, often to align local midnight to solar time.
228
229Relevant Time Scales
230====================
231
232`International Atomic Time
233<https://en.wikipedia.org/wiki/International_Atomic_Time>`__ (TAI) is a time
234scale based on averaging clocks that count in SI seconds. TAI is a monotonic
235and continuous time scale.
236
237`Universal Time <https://en.wikipedia.org/wiki/Universal_Time>`__ (UT) is a
238time scale based on Earth’s rotation. UT is a discontinuous time scale as it
239requires occasional adjustments (`leap seconds
240<https://en.wikipedia.org/wiki/Leap_second>`__) to maintain alignment to
241changes in Earth’s rotation. Thus the difference between TAI and UT varies
242over time. There are several variants of UT, with `UTC
243<https://en.wikipedia.org/wiki/Coordinated_Universal_Time>`__ being the most
244common.
245
246UT times are independent of location. UT is the basis for Standard Time
247(or "local time") which is the time at a particular location. Standard
248time has a fixed offset from UT at any given instant, primarily
249influenced by longitude, but the offset may be adjusted ("daylight
250saving time") to align standard time to the local solar time. In a sense
251local time is "more discontinuous" than UT.
252
253`POSIX Time <https://tools.ietf.org/html/rfc8536#section-2>`__ is a time scale
254that counts seconds since the "POSIX epoch" at 1970-01-01T00:00:00Z (i.e. the
255start of 1970 UTC). `UNIX Time
256<https://tools.ietf.org/html/rfc8536#section-2>`__ is an extension of POSIX
257time using negative values to represent times before the POSIX epoch. Both of
258these scales assume that every day has exactly 86400 seconds. In normal use
259instants in these scales correspond to times in the UTC scale, so they inherit
260the discontinuity.
261
262The continuous analogue is `UNIX Leap Time
263<https://tools.ietf.org/html/rfc8536#section-2>`__ which is UNIX time plus all
264leap-second corrections added after the POSIX epoch (when TAI-UTC was 8 s).
265
266Example of Time Scale Differences
267---------------------------------
268
269A positive leap second was introduced at the end of 2016, increasing the
270difference between TAI and UTC from 36 seconds to 37 seconds. There was
271no leap second introduced at the end of 1999, when the difference
272between TAI and UTC was only 32 seconds. The following table shows
273relevant civil and epoch times in several scales:
274
275==================== ========== =================== ======= ==============
276UTC Date             UNIX time  TAI Date            TAI-UTC UNIX Leap Time
277==================== ========== =================== ======= ==============
2781970-01-01T00:00:00Z 0          1970-01-01T00:00:08 +8      0
2791999-12-31T23:59:28Z 946684768  2000-01-01T00:00:00 +32     946684792
2801999-12-31T23:59:59Z 946684799  2000-01-01T00:00:31 +32     946684823
2812000-01-01T00:00:00Z 946684800  2000-01-01T00:00:32 +32     946684824
2822016-12-31T23:59:59Z 1483228799 2017-01-01T00:00:35 +36     1483228827
2832016-12-31T23:59:60Z undefined  2017-01-01T00:00:36 +36     1483228828
2842017-01-01T00:00:00Z 1483228800 2017-01-01T00:00:37 +37     1483228829
285==================== ========== =================== ======= ==============
286
287Functional Requirements
288-----------------------
289
290The Zephyr tick counter has no concept of leap seconds or standard time
291offsets and is a continuous time scale. However it can be relatively
292inaccurate, with drifts as much as three minutes per hour (assuming an RC
293timer with 5% tolerance).
294
295There are two stages required to support conversion between Zephyr time and
296common human time scales:
297
298* Translation between the continuous but inaccurate Zephyr time scale and an
299  accurate external stable time scale;
300* Translation between the stable time scale and the (possibly discontinuous)
301  civil time scale.
302
303The API around :c:func:`timeutil_sync_state_update()` supports the first step
304of converting between continuous time scales.
305
306The second step requires external information including schedules of leap
307seconds and local time offset changes. This may be best provided by an
308external library, and is not currently part of the time utility APIs.
309
310Selecting an External Source and Time Scale
311-------------------------------------------
312
313If an application requires civil time accuracy within several seconds then UTC
314could be used as the stable time source. However, if the external source
315adjusts to a leap second there will be a discontinuity: the elapsed time
316between two observations taken at 1 Hz is not equal to the numeric difference
317between their timestamps.
318
319For precise activities a continuous scale that is independent of local and
320solar adjustments simplifies things considerably. Suitable continuous scales
321include:
322
323- GPS time: epoch of 1980-01-06T00:00:00Z, continuous following TAI with an
324  offset of TAI-GPS=19 s.
325- Bluetooth Mesh time: epoch of 2000-01-01T00:00:00Z, continuous following TAI
326  with an offset of -32.
327- UNIX Leap Time: epoch of 1970-01-01T00:00:00Z, continuous following TAI with
328  an offset of -8.
329
330Because C and Zephyr library functions support conversion between integral and
331calendar time representations using the UNIX epoch, UNIX Leap Time is an ideal
332choice for the external time scale.
333
334The mechanism used to populate synchronization points is not relevant: it may
335involve reading from a local high-precision RTC peripheral, exchanging packets
336over a network using a protocol like NTP or PTP, or processing NMEA messages
337received a GPS with or without a 1pps signal.
338
339``timespec`` Concepts
340=====================
341
342Originally from POSIX, ``struct timespec`` has been a part of the C standard
343since C11. The definition of ``struct timespec`` is as shown below.
344
345.. code-block:: c
346
347   struct timespec {
348       time_t tv_sec;  /* seconds */
349       long   tv_nsec; /* nanoseconds */
350   };
351
352.. _note:
353
354    The C standard does not define the size of ``time_t``. However, Zephyr
355    uses 64-bits for ``time_t``. The ``long`` type is required to be at least
356    32-bits, but usually matches the word size of the architecture. Both
357    elements of ``struct timespec`` are signed integers. ``time_t`` is defined
358    to be 64-bits both for historical reasons and to be robust enough to
359    represent times in the future.
360
361The ``tv_nsec`` field is only valid with values in the range ``[0, 999999999]``. The
362``tv_sec`` field is the number of seconds since the epoch. If ``struct timespec`` is
363used to express a difference, the ``tv_sec`` field may fall into a negative range.
364