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