ocaml-opentelemetry/ptime/Ptime/index.html
2025-07-23 14:08:20 +00:00

41 lines
43 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Ptime (ptime.Ptime)</title><meta charset="utf-8"/><link rel="stylesheet" href="../../_odoc-theme/odoc.css"/><meta name="generator" content="odoc 3.1.0"/><meta name="viewport" content="width=device-width,initial-scale=1.0"/><script src="../../highlight.pack.js"></script><script>hljs.initHighlightingOnLoad();</script></head><body class="odoc"><nav class="odoc-nav"><a href="../index.html">Up</a> <a href="../../index.html">Index</a> &#x00BB; <a href="../index.html">ptime</a> &#x00BB; Ptime</nav><header class="odoc-preamble"><h1>Module <code><span>Ptime</span></code></h1><p>POSIX time values.</p><p>Consult the <a href="#basics" title="basics">basics</a> and a few <a href="#notes" title="notes">notes and limitations</a>.</p><p><b>References</b></p><ul><li>The Open Group. <a href="http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_15">The Open Group Base Specifications Issue 7, section 4.15 Seconds Since the Epoch</a>. 2013</li><li>G. Klyne et al. <a href="http://tools.ietf.org/html/rfc3339"><em>Date and Time on the Internet: Timestamps</em></a>. RFC 3339, 2002.</li></ul></header><div class="odoc-tocs"><nav class="odoc-toc odoc-local-toc"><ul><li><a href="#timespans">POSIX time spans</a></li><li><a href="#timestamps">POSIX timestamps</a></li><li><a href="#predicates">Predicates</a></li><li><a href="#posix_arithmetic">POSIX arithmetic</a></li><li><a href="#tz_offset">Time zone offsets between local and UTC timelines</a></li><li><a href="#date_time">Date-time value conversions</a><ul><li><a href="#datetimes">Date and time</a></li><li><a href="#dates">Date</a></li><li><a href="#years">Year</a></li><li><a href="#weekdays">Week days</a></li></ul></li><li><a href="#rfc3339">RFC 3339 timestamp conversions</a></li><li><a href="#print">Pretty printing</a></li><li><a href="#basics">Basics</a></li><li><a href="#notes">Notes and limitations</a></li></ul></nav></div><div class="odoc-content"><h2 id="timespans"><a href="#timespans" class="anchor"></a>POSIX time spans</h2><div class="odoc-spec"><div class="spec type anchored" id="type-span"><a href="#type-span" class="anchor"></a><code><span><span class="keyword">type</span> span</span></code></div><div class="spec-doc"><p>The type for signed picosecond precision POSIX time spans. A value of this type represent the POSIX duration between two POSIX timestamps.</p></div></div><div class="odoc-spec"><div class="spec module anchored" id="module-Span"><a href="#module-Span" class="anchor"></a><code><span><span class="keyword">module</span> <a href="Span/index.html">Span</a></span><span> : <span class="keyword">sig</span> ... <span class="keyword">end</span></span></code></div><div class="spec-doc"><p>POSIX time spans.</p></div></div><h2 id="timestamps"><a href="#timestamps" class="anchor"></a>POSIX timestamps</h2><div class="odoc-spec"><div class="spec type anchored" id="type-t"><a href="#type-t" class="anchor"></a><code><span><span class="keyword">type</span> t</span></code></div><div class="spec-doc"><p>The type for picosecond precision POSIX timestamps in the range [<a href="#val-min"><code>min</code></a>;<a href="#val-max"><code>max</code></a>]. Note that POSIX timestamps, and hence values of this type, are by definition always on the UTC timeline.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-v"><a href="#val-v" class="anchor"></a><code><span><span class="keyword">val</span> v : <span><span>(int * int64)</span> <span class="arrow">&#45;&gt;</span></span> <a href="#type-t">t</a></span></code></div><div class="spec-doc"><p><code>v s</code> is <code>of_span (Span.v s)</code> but raise <code>Invalid_argument</code> if <code>s</code> is not in the right range. Use <a href="Span/index.html#val-of_d_ps"><code>Span.of_d_ps</code></a> and <a href="#val-of_span"><code>of_span</code></a> to deal with untrusted input.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-epoch"><a href="#val-epoch" class="anchor"></a><code><span><span class="keyword">val</span> epoch : <a href="#type-t">t</a></span></code></div><div class="spec-doc"><p><code>epoch</code> is 1970-01-01 00:00:00 UTC.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-min"><a href="#val-min" class="anchor"></a><code><span><span class="keyword">val</span> min : <a href="#type-t">t</a></span></code></div><div class="spec-doc"><p><code>min</code> is 0000-01-01 00:00:00 UTC, the earliest timestamp representable by <a href="#"><code>Ptime</code></a>.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-max"><a href="#val-max" class="anchor"></a><code><span><span class="keyword">val</span> max : <a href="#type-t">t</a></span></code></div><div class="spec-doc"><p><code>max</code> is 9999-12-31 23:59:59.999999999999 UTC, the latest timestamp representable by <a href="#"><code>Ptime</code></a>.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-of_span"><a href="#val-of_span" class="anchor"></a><code><span><span class="keyword">val</span> of_span : <span><a href="#type-span">span</a> <span class="arrow">&#45;&gt;</span></span> <span><a href="#type-t">t</a> option</span></span></code></div><div class="spec-doc"><p><code>of_span d</code> is the POSIX time stamp that:</p><ul><li>Happens at the POSIX span <code>d</code> <em>after</em> <a href="#val-epoch"><code>epoch</code></a> if <code>d</code> is positive.</li><li>Happens at the POSIX span <code>d</code> <em>before</em> <a href="#val-epoch"><code>epoch</code></a> if <code>d</code> is negative.</li></ul><p><code>None</code> is returned if the timestamp is not in the range [<a href="#val-min"><code>min</code></a>;<a href="#val-max"><code>max</code></a>].</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-to_span"><a href="#val-to_span" class="anchor"></a><code><span><span class="keyword">val</span> to_span : <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> <a href="#type-span">span</a></span></code></div><div class="spec-doc"><p><code>to_span t</code> is the signed POSIX span that happen between <code>t</code> and <a href="#val-epoch"><code>epoch</code></a>:</p><ul><li>If the number is positive <code>t</code> happens <em>after</em> <a href="#val-epoch"><code>epoch</code></a>.</li><li>If the number is negative <code>t</code> happens <em>before</em> <a href="#val-epoch"><code>epoch</code></a>.</li></ul></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-of_float_s"><a href="#val-of_float_s" class="anchor"></a><code><span><span class="keyword">val</span> of_float_s : <span>float <span class="arrow">&#45;&gt;</span></span> <span><a href="#type-t">t</a> option</span></span></code></div><div class="spec-doc"><p><code>of_float_s d</code> is like <a href="#val-of_span"><code>of_span</code></a> but with <code>d</code> as a floating point second POSIX span <code>d</code>. This function is compatible with the result of <code>Unix.gettimeofday</code>. Decimal fractional seconds beyond <code>1e-12</code> are truncated.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-to_float_s"><a href="#val-to_float_s" class="anchor"></a><code><span><span class="keyword">val</span> to_float_s : <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> float</span></code></div><div class="spec-doc"><p><code>to_float_s t</code> is like <a href="#val-to_span"><code>to_span</code></a> but returns a floating point second POSIX span.</p><p><b>Warning.</b> Due to floating point inaccuracies do not expect the function to round trip with <a href="#val-of_float_s"><code>of_float_s</code></a>; especially near <a href="#val-min"><code>Ptime.min</code></a> and <a href="#val-max"><code>Ptime.max</code></a>.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-truncate"><a href="#val-truncate" class="anchor"></a><code><span><span class="keyword">val</span> truncate : <span><span class="label">frac_s</span>:int <span class="arrow">&#45;&gt;</span></span> <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> <a href="#type-t">t</a></span></code></div><div class="spec-doc"><p><code>truncate ~frac_s t</code> is <code>t</code> truncated to the <code>frac_s</code> decimal fractional second. Effectively this reduces precision without rounding, the timestamp remains in the second it is in. <code>frac_s</code> is clipped to the range [<code>0</code>;<code>12</code>].</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-frac_s"><a href="#val-frac_s" class="anchor"></a><code><span><span class="keyword">val</span> frac_s : <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> <a href="#type-span">span</a></span></code></div><div class="spec-doc"><p><code>frac_s t</code> is the (positive) fractional second duration in <code>t</code>.</p></div></div><h2 id="predicates"><a href="#predicates" class="anchor"></a>Predicates</h2><div class="odoc-spec"><div class="spec value anchored" id="val-equal"><a href="#val-equal" class="anchor"></a><code><span><span class="keyword">val</span> equal : <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> bool</span></code></div><div class="spec-doc"><p><code>equal t t'</code> is <code>true</code> iff <code>t</code> and <code>t'</code> are the same timestamps.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-compare"><a href="#val-compare" class="anchor"></a><code><span><span class="keyword">val</span> compare : <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> int</span></code></div><div class="spec-doc"><p><code>compare t t'</code> is a total order on timestamps that is compatible with timeline order.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-is_earlier"><a href="#val-is_earlier" class="anchor"></a><code><span><span class="keyword">val</span> is_earlier : <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> <span><span class="label">than</span>:<a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> bool</span></code></div><div class="spec-doc"><p><code>is_earlier t ~than</code> is <code>true</code> iff <code>compare t than = -1</code>.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-is_later"><a href="#val-is_later" class="anchor"></a><code><span><span class="keyword">val</span> is_later : <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> <span><span class="label">than</span>:<a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> bool</span></code></div><div class="spec-doc"><p><code>is_later t than</code> is <code>true</code> iff <code>compare t than = 1</code>.</p></div></div><h2 id="posix_arithmetic"><a href="#posix_arithmetic" class="anchor"></a>POSIX arithmetic</h2><p><b>WARNING.</b> A POSIX time span is not equal to an SI second based time span, see the <a href="#basics" title="basics">basics</a>. Do not use these functions to perform calendar arithmetic or measure wall-clock durations, you will fail.</p><div class="odoc-spec"><div class="spec value anchored" id="val-add_span"><a href="#val-add_span" class="anchor"></a><code><span><span class="keyword">val</span> add_span : <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> <span><a href="#type-span">span</a> <span class="arrow">&#45;&gt;</span></span> <span><a href="#type-t">t</a> option</span></span></code></div><div class="spec-doc"><p><code>add_span t d</code> is timestamp <code>t + d</code>, that is <code>t</code> with the signed POSIX span <code>d</code> added. <code>None</code> is returned if the result is not in the range [<a href="#val-min"><code>min</code></a>;<a href="#val-max"><code>max</code></a>].</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-sub_span"><a href="#val-sub_span" class="anchor"></a><code><span><span class="keyword">val</span> sub_span : <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> <span><a href="#type-span">span</a> <span class="arrow">&#45;&gt;</span></span> <span><a href="#type-t">t</a> option</span></span></code></div><div class="spec-doc"><p><code>sub_span t d</code> is the timestamp <code>t - d</code>, that is <code>t</code> with the signed POSIX span <code>d</code> subtracted. <code>None</code> is returned if the result is not in the range [<a href="#val-min"><code>min</code></a>;<a href="#val-max"><code>max</code></a>].</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-diff"><a href="#val-diff" class="anchor"></a><code><span><span class="keyword">val</span> diff : <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> <a href="#type-span">span</a></span></code></div><div class="spec-doc"><p><code>diff t t'</code> is the signed POSIX span <code>t - t'</code> that happens between the timestamps <code>t</code> and <code>t'</code>.</p></div></div><h2 id="tz_offset"><a href="#tz_offset" class="anchor"></a>Time zone offsets between local and UTC timelines</h2><div class="odoc-spec"><div class="spec type anchored" id="type-tz_offset_s"><a href="#type-tz_offset_s" class="anchor"></a><code><span><span class="keyword">type</span> tz_offset_s</span><span> = int</span></code></div><div class="spec-doc"><p>The type for time zone offsets between local and UTC timelines in seconds. This is the signed difference in seconds between the local timeline and the UTC timeline:</p><pre class="language-ocaml"><code> tz_offset_s = local - UTC</code></pre><ul><li>A value of <code>-3600</code> means that the local timeline is sixty minutes <em>behind</em> the UTC timeline.</li><li>A value of <code>3600</code> means that the local timeline is sixty minutes <em>ahead</em> the UTC timeline.</li></ul></div></div><h2 id="date_time"><a href="#date_time" class="anchor"></a>Date-time value conversions</h2><p>A <em>date-time</em> represents a point on the UTC timeline by pairing a date in the proleptic Gregorian calendar and a second precision daytime in a local timeline with stated relationship to the UTC timeline.</p><div class="odoc-spec"><div class="spec type anchored" id="type-date"><a href="#type-date" class="anchor"></a><code><span><span class="keyword">type</span> date</span><span> = int * int * int</span></code></div><div class="spec-doc"><p>The type for big-endian proleptic Gregorian dates. A triple <code>(y, m, d)</code> with:</p><ul><li><code>y</code> the year from <code>0</code> to <code>9999</code>. <code>0</code> denotes -1 BCE (this follows the <a href="http://www.iso.org/iso/home/standards/iso8601.htm">ISO 8601</a> convention).</li><li><code>m</code> is the month from <code>1</code> to <code>12</code></li><li><code>d</code> is the day from <code>1</code> to <code>28</code>, <code>29</code>, <code>30</code> or <code>31</code> depending on <code>m</code> and <code>y</code></li></ul><p>A date is said to be <em>valid</em> iff the values <code>(y, m, d)</code> are in the range mentioned above and represent an existing date in the proleptic Gregorian calendar.</p></div></div><div class="odoc-spec"><div class="spec type anchored" id="type-time"><a href="#type-time" class="anchor"></a><code><span><span class="keyword">type</span> time</span><span> = <span>(int * int * int)</span> * <a href="#type-tz_offset_s">tz_offset_s</a></span></code></div><div class="spec-doc"><p>The type for daytimes on a local timeline. Pairs a triple <code>(hh, mm, ss)</code> denoting the time on the local timeline and a <code>tz_offset</code> stating the <a href="#type-tz_offset_s" title="tz_offset_s">relationship</a> of the local timeline to the UTC timeline.</p><p>The <code>(hh, mm, ss)</code> components are understood and constrainted as follows:</p><ul><li><code>hh</code> is the hour from <code>0</code> to <code>23</code>.</li><li><code>mm</code> is the minute from <code>0</code> to <code>59</code>.</li><li><code>ss</code> is the seconds from <code>0</code> to <code>60</code>. <code>60</code> may happen whenever a leap second is added.</li></ul><p>A <code>time</code> value is said to be <em>valid</em> iff the values <code>(hh, mm, ss)</code> are in the ranges mentioned above.</p></div></div><h3 id="datetimes"><a href="#datetimes" class="anchor"></a>Date and time</h3><div class="odoc-spec"><div class="spec value anchored" id="val-of_date_time"><a href="#val-of_date_time" class="anchor"></a><code><span><span class="keyword">val</span> of_date_time : <span><span>(<a href="#type-date">date</a> * <a href="#type-time">time</a>)</span> <span class="arrow">&#45;&gt;</span></span> <span><a href="#type-t">t</a> option</span></span></code></div><div class="spec-doc"><p><code>of_date_time dt</code> is the POSIX timestamp corresponding to date-time <code>dt</code> or <code>None</code> if <code>dt</code> has an <a href="#type-date" title="date">invalid date</a>, <a href="#type-time" title="time">invalid time</a> or the date-time is not in the range [<a href="#val-min"><code>min</code></a>;<a href="#val-max"><code>max</code></a>].</p><p><b>Leap seconds.</b> Any date-time with a seconds value of <code>60</code>, hence representing a leap second addition, is mapped to the date-time that happens 1 second later. Any date-time with a seconds value of <code>59</code> is mapped to the POSIX timestamp that represents this instant, if a leap second was subtracted at that point, this is the POSIX timestamp that represents this inexisting instant. See the <a href="#basics" title="basics">basics</a>.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-to_date_time"><a href="#val-to_date_time" class="anchor"></a><code><span><span class="keyword">val</span> to_date_time : <span><span class="optlabel">?tz_offset_s</span>:<a href="#type-tz_offset_s">tz_offset_s</a> <span class="arrow">&#45;&gt;</span></span> <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> <a href="#type-date">date</a> * <a href="#type-time">time</a></span></code></div><div class="spec-doc"><p><code>to_date_time ~tz_offset_s t</code> is the date-time of the timestamp <code>t</code>.</p><p><code>tz_offset_s</code> hints the time zone offset used for the resulting daytime component (defaults to <code>0</code>, i.e. UTC). The offset is not honoured and fallbacks to <code>0</code> in case the resulting date-time rendering of the timestamp would yield an <a href="#type-date" title="date">invalid date</a>. This means that you should always interpret the resulting time component with the time zone offset it is paired with in the result and not assume it will be the one you gave to the function. Note that for real-world time zone offsets the fallback to <code>0</code> will only happen around <a href="#val-min"><code>Ptime.min</code></a> and <a href="#val-max"><code>Ptime.max</code></a>. Formally the fallback occurs whenever <code>add_span t (Span.of_int_s tz_offset_s)</code> is <code>None</code>.</p><p><b>Leap seconds.</b> No POSIX timestamp can represent a date-time with a leap second added, hence this function will never return a date-time with a <code>60</code> seconds value. This function does return inexisting UTC date-times with <code>59</code> seconds whenever a leap second is subtracted since POSIX timestamps do represent them. See the <a href="#basics" title="basics">basics</a>.</p><p><b>Subsecond precision.</b> POSIX timestamps with subsecond precision are floored, i.e. the date-time always has the second mentioned in the timestamp.</p></div></div><h3 id="dates"><a href="#dates" class="anchor"></a>Date</h3><div class="odoc-spec"><div class="spec value anchored" id="val-of_date"><a href="#val-of_date" class="anchor"></a><code><span><span class="keyword">val</span> of_date : <span><span class="optlabel">?tz_offset_s</span>:<a href="#type-tz_offset_s">tz_offset_s</a> <span class="arrow">&#45;&gt;</span></span> <span><a href="#type-date">date</a> <span class="arrow">&#45;&gt;</span></span> <span><a href="#type-t">t</a> option</span></span></code></div><div class="spec-doc"><p><code>of_date d</code> is <code>of_date_time (d, ((00, 00, 00), tz_offset_s))</code>. <code>tz_offset_s</code> defaults to 0, i.e. UTC.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-to_date"><a href="#val-to_date" class="anchor"></a><code><span><span class="keyword">val</span> to_date : <span><span class="optlabel">?tz_offset_s</span>:<a href="#type-tz_offset_s">tz_offset_s</a> <span class="arrow">&#45;&gt;</span></span> <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> <a href="#type-date">date</a></span></code></div><div class="spec-doc"><p><code>to_date t</code> is <code>fst (to_date_time ?tz_offset_s t)</code>.</p></div></div><h3 id="years"><a href="#years" class="anchor"></a>Year</h3><div class="odoc-spec"><div class="spec value anchored" id="val-of_year"><a href="#val-of_year" class="anchor"></a><code><span><span class="keyword">val</span> of_year : <span><span class="optlabel">?tz_offset_s</span>:<a href="#type-tz_offset_s">tz_offset_s</a> <span class="arrow">&#45;&gt;</span></span> <span>int <span class="arrow">&#45;&gt;</span></span> <span><a href="#type-t">t</a> option</span></span></code></div><div class="spec-doc"><p><code>of_year y</code> is <code>of_date ?tz_offset_s (y, 01, 01)</code>.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-to_year"><a href="#val-to_year" class="anchor"></a><code><span><span class="keyword">val</span> to_year : <span><span class="optlabel">?tz_offset_s</span>:<a href="#type-tz_offset_s">tz_offset_s</a> <span class="arrow">&#45;&gt;</span></span> <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> int</span></code></div><div class="spec-doc"><p><code>to_year t</code> is the first component of <code>(to_date ?tz_offset_s t))</code> but more efficient.</p></div></div><h3 id="weekdays"><a href="#weekdays" class="anchor"></a>Week days</h3><div class="odoc-spec"><div class="spec type anchored" id="type-weekday"><a href="#type-weekday" class="anchor"></a><code><span><span class="keyword">type</span> weekday</span><span> = </span><span>[ </span></code><ol><li id="type-weekday.Sun" class="def variant constructor anchored"><a href="#type-weekday.Sun" class="anchor"></a><code><span>| </span><span>`Sun</span></code></li><li id="type-weekday.Mon" class="def variant constructor anchored"><a href="#type-weekday.Mon" class="anchor"></a><code><span>| </span><span>`Mon</span></code></li><li id="type-weekday.Tue" class="def variant constructor anchored"><a href="#type-weekday.Tue" class="anchor"></a><code><span>| </span><span>`Tue</span></code></li><li id="type-weekday.Wed" class="def variant constructor anchored"><a href="#type-weekday.Wed" class="anchor"></a><code><span>| </span><span>`Wed</span></code></li><li id="type-weekday.Thu" class="def variant constructor anchored"><a href="#type-weekday.Thu" class="anchor"></a><code><span>| </span><span>`Thu</span></code></li><li id="type-weekday.Fri" class="def variant constructor anchored"><a href="#type-weekday.Fri" class="anchor"></a><code><span>| </span><span>`Fri</span></code></li><li id="type-weekday.Sat" class="def variant constructor anchored"><a href="#type-weekday.Sat" class="anchor"></a><code><span>| </span><span>`Sat</span></code></li></ol><code><span> ]</span></code></div><div class="spec-doc"><p>The type for the days of the 7-day week.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-weekday"><a href="#val-weekday" class="anchor"></a><code><span><span class="keyword">val</span> weekday : <span><span class="optlabel">?tz_offset_s</span>:<a href="#type-tz_offset_s">tz_offset_s</a> <span class="arrow">&#45;&gt;</span></span> <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> <a href="#type-weekday">weekday</a></span></code></div><div class="spec-doc"><p><code>weekday ~tz_offset_s t</code> is the day in the 7-day week of timestamp <code>t</code> expressed in the time zone offset <code>ts_offset_s</code> (defaults to <code>0</code>).</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-weekday_num"><a href="#val-weekday_num" class="anchor"></a><code><span><span class="keyword">val</span> weekday_num : <span><span class="optlabel">?tz_offset_s</span>:<a href="#type-tz_offset_s">tz_offset_s</a> <span class="arrow">&#45;&gt;</span></span> <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> int</span></code></div><div class="spec-doc"><p><code>weekday_num</code> is like <a href="#val-weekday"><code>weekday</code></a> but returns a weekday number, 0 is sunday, 1 is monday, …, 6 is saturday etc.</p></div></div><h2 id="rfc3339"><a href="#rfc3339" class="anchor"></a>RFC 3339 timestamp conversions</h2><div class="odoc-spec"><div class="spec type anchored" id="type-error_range"><a href="#type-error_range" class="anchor"></a><code><span><span class="keyword">type</span> error_range</span><span> = int * int</span></code></div><div class="spec-doc"><p>The type for error ranges, starting and ending position.</p></div></div><div class="odoc-spec"><div class="spec type anchored" id="type-rfc3339_error"><a href="#type-rfc3339_error" class="anchor"></a><code><span><span class="keyword">type</span> rfc3339_error</span><span> = </span><span>[ </span></code><ol><li id="type-rfc3339_error.Invalid_stamp" class="def variant constructor anchored"><a href="#type-rfc3339_error.Invalid_stamp" class="anchor"></a><code><span>| </span><span>`Invalid_stamp</span></code></li><li id="type-rfc3339_error.Eoi" class="def variant constructor anchored"><a href="#type-rfc3339_error.Eoi" class="anchor"></a><code><span>| </span><span>`Eoi</span></code></li><li id="type-rfc3339_error.Exp_chars" class="def variant constructor anchored"><a href="#type-rfc3339_error.Exp_chars" class="anchor"></a><code><span>| </span><span>`Exp_chars <span class="keyword">of</span> <span>char list</span></span></code></li><li id="type-rfc3339_error.Trailing_input" class="def variant constructor anchored"><a href="#type-rfc3339_error.Trailing_input" class="anchor"></a><code><span>| </span><span>`Trailing_input</span></code></li></ol><code><span> ]</span></code></div><div class="spec-doc"><p>The type for RFC 3339 timestamp parsing errors. <code>`Invalid_stamp</code> means that either the time stamp is not in the range [<a href="#val-min"><code>min</code></a>;<a href="#val-max"><code>max</code></a>], or the date is invalid, or one of the fields is not in the right range.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-pp_rfc3339_error"><a href="#val-pp_rfc3339_error" class="anchor"></a><code><span><span class="keyword">val</span> pp_rfc3339_error : <span><a href="../../ocaml/Stdlib/Format/index.html#type-formatter">Stdlib.Format.formatter</a> <span class="arrow">&#45;&gt;</span></span> <span><a href="#type-rfc3339_error">rfc3339_error</a> <span class="arrow">&#45;&gt;</span></span> unit</span></code></div><div class="spec-doc"><p><code>pp_rfc3339_error ppf e</code> prints an unspecified representation of <code>e</code> on <code>ppf</code>.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-rfc3339_error_to_msg"><a href="#val-rfc3339_error_to_msg" class="anchor"></a><code><span><span class="keyword">val</span> rfc3339_error_to_msg :
<span><span><span>(<span class="type-var">'a</span>, <span>[ <span>`RFC3339 of <a href="#type-error_range">error_range</a> * <a href="#type-rfc3339_error">rfc3339_error</a></span> ]</span>)</span> <a href="../../ocaml/Stdlib/index.html#type-result">result</a></span> <span class="arrow">&#45;&gt;</span></span>
<span><span>(<span class="type-var">'a</span>, <span>[&gt; <span>`Msg of string</span> ]</span>)</span> <a href="../../ocaml/Stdlib/index.html#type-result">result</a></span></span></code></div><div class="spec-doc"><p><code>rfc3339_error_to_msg r</code> converts RFC 3339 parse errors to error messages.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-rfc3339_string_error"><a href="#val-rfc3339_string_error" class="anchor"></a><code><span><span class="keyword">val</span> rfc3339_string_error :
<span><span><span>(<span class="type-var">'a</span>, <span>[ <span>`RFC3339 of <a href="#type-error_range">error_range</a> * <a href="#type-rfc3339_error">rfc3339_error</a></span> ]</span>)</span> <a href="../../ocaml/Stdlib/index.html#type-result">result</a></span> <span class="arrow">&#45;&gt;</span></span>
<span><span>(<span class="type-var">'a</span>, string)</span> <a href="../../ocaml/Stdlib/index.html#type-result">result</a></span></span></code></div><div class="spec-doc"><p><code>rfc3339_string_error r</code> converts RFC 3339 parse errors errors to string errors.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-of_rfc3339"><a href="#val-of_rfc3339" class="anchor"></a><code><span><span class="keyword">val</span> of_rfc3339 :
<span><span class="optlabel">?strict</span>:bool <span class="arrow">&#45;&gt;</span></span>
<span><span class="optlabel">?sub</span>:bool <span class="arrow">&#45;&gt;</span></span>
<span><span class="optlabel">?start</span>:int <span class="arrow">&#45;&gt;</span></span>
<span>string <span class="arrow">&#45;&gt;</span></span>
<span><span>(<a href="#type-t">t</a> * <span><a href="#type-tz_offset_s">tz_offset_s</a> option</span> * int, <span>[&gt; <span>`RFC3339 of <a href="#type-error_range">error_range</a> * <a href="#type-rfc3339_error">rfc3339_error</a></span> ]</span>)</span>
<a href="../../ocaml/Stdlib/index.html#type-result">result</a></span></span></code></div><div class="spec-doc"><p><code>of_rfc3339 ~strict ~sub ~start s</code> parses an RFC 3339 <a href="https://tools.ietf.org/html/rfc3339#section-5.6"><code>date-time</code></a> starting at <code>start</code> (defaults to <code>0</code>) in <code>s</code> to a triple <code>(t, tz, count)</code> with:</p><ul><li><code>t</code> the POSIX timestamp (hence on the UTC timeline).</li><li><code>tz</code>, the optional <a href="#type-tz_offset_s" title="tz_offset_s">time zone offset</a> found in the timestamp. <code>None</code> is returned iff the date-time satisfies the <a href="https://tools.ietf.org/html/rfc3339#section-4.3">unknown local offset convention</a>.</li><li><code>count</code> the number of bytes read starting at <code>start</code> to parse the timestamp. If <code>sub</code> is <code>false</code> (default) this is always <code>String.length s - start</code> and <code>Error `Trailing_input</code> is returned if there are still bytes in <code>s</code> after the date-time was parsed. Use <code>~sub:true</code> for allowing trailing input to exist.</li><li><code>strict</code> if <code>false</code> (default) the pasring function does not error on timestamp with lowercase <code>'T'</code> or <code>'Z'</code> characters, or space separated date and times, and `hhmm` and `hh` timezone offsets (strict mandates <code>hh:mm</code>). This allows to parse a slightly larger subset of ISO 8601 than what RFC 3339 allows</li></ul><p><b>Notes and limitations.</b></p><ul><li>If <code>start</code> is not an index of <code>s</code>, <code>Error ((start, start), `Eoi)</code> is returned.</li><li>RFC 3339 allows a few degenerate (I say) timestamps with non-zero time zone offsets to be parsed at the boundaries that correspond to timestamps that cannot be expressed in UTC in RFC 3339 itself (e.g. <code>0000-01-01T00:00:00+00:01</code>). The function errors on these timestamps with <code>`Invalid_stamp</code> as they cannot be represented in the range [<a href="#val-min"><code>min</code></a>;<a href="#val-max"><code>max</code></a>].</li><li>Leap seconds are allowed on any date-time and handled as in <a href="#val-of_date_time"><code>of_date_time</code></a></li><li>Fractional parts beyond the picosecond (<code>1e-12</code>) are truncated.</li></ul></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-to_rfc3339"><a href="#val-to_rfc3339" class="anchor"></a><code><span><span class="keyword">val</span> to_rfc3339 :
<span><span class="optlabel">?space</span>:bool <span class="arrow">&#45;&gt;</span></span>
<span><span class="optlabel">?frac_s</span>:int <span class="arrow">&#45;&gt;</span></span>
<span><span class="optlabel">?tz_offset_s</span>:<a href="#type-tz_offset_s">tz_offset_s</a> <span class="arrow">&#45;&gt;</span></span>
<span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span>
string</span></code></div><div class="spec-doc"><p><code>to_rfc3339_tz ~space ~frac_s ~tz_offset_s t</code> formats the timestamp <code>t</code> according to a RFC 3339 <a href="https://tools.ietf.org/html/rfc3339#section-5.6"><code>date-time</code></a> production with:</p><ul><li><code>tz_offset_s</code> hints the time zone offset to use, use <code>0</code> for UTC. The hint is ignored in the following cases: if <code>tz_offset_s</code> is not an integral number of minutes and its magnitude not in the range permitted by the standard, if <code>add_span t (Span.of_int_s tz_offset_s)</code> is <code>None</code> (the resulting timestamp rendering would not be RFC 3339 compliant). If either the hint is ignored or <code>tz_offset_s</code> is unspecified then the <a href="https://tools.ietf.org/html/rfc3339#section-4.3">unknown local offset convention</a> is used to render the time zone component.</li><li><code>frac_s</code>, clipped to the range [<code>0</code>;<code>12</code>] specifies that exactly <code>frac_s</code> decimal digits of the fractional second of <code>t</code> are rendered (defaults to <code>0</code>).</li><li><code>space</code> if <code>true</code> the date and time separator is a space rather than a <code>'T'</code> (not recommended but may be allowed by the protocol you are dealing with, defaults to <code>false</code>).</li></ul></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-pp_rfc3339"><a href="#val-pp_rfc3339" class="anchor"></a><code><span><span class="keyword">val</span> pp_rfc3339 :
<span><span class="optlabel">?space</span>:bool <span class="arrow">&#45;&gt;</span></span>
<span><span class="optlabel">?frac_s</span>:int <span class="arrow">&#45;&gt;</span></span>
<span><span class="optlabel">?tz_offset_s</span>:<a href="#type-tz_offset_s">tz_offset_s</a> <span class="arrow">&#45;&gt;</span></span>
<span>unit <span class="arrow">&#45;&gt;</span></span>
<span><a href="../../ocaml/Stdlib/Format/index.html#type-formatter">Stdlib.Format.formatter</a> <span class="arrow">&#45;&gt;</span></span>
<span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span>
unit</span></code></div><div class="spec-doc"><p><code>pp_rfc3339 ?space ?frac_s ?tz_offset_s () ppf t</code> is <code>Format.fprintf ppf &quot;%s&quot; (to_rfc3339 ?space ?frac_s ?tz_offset_s t)</code>.</p></div></div><h2 id="print"><a href="#print" class="anchor"></a>Pretty printing</h2><div class="odoc-spec"><div class="spec value anchored" id="val-pp_human"><a href="#val-pp_human" class="anchor"></a><code><span><span class="keyword">val</span> pp_human :
<span><span class="optlabel">?frac_s</span>:int <span class="arrow">&#45;&gt;</span></span>
<span><span class="optlabel">?tz_offset_s</span>:<a href="#type-tz_offset_s">tz_offset_s</a> <span class="arrow">&#45;&gt;</span></span>
<span>unit <span class="arrow">&#45;&gt;</span></span>
<span><a href="../../ocaml/Stdlib/Format/index.html#type-formatter">Stdlib.Format.formatter</a> <span class="arrow">&#45;&gt;</span></span>
<span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span>
unit</span></code></div><div class="spec-doc"><p><code>pp_human ~frac_s ~tz_offset_s () ppf t</code> prints an unspecified, human readable, locale-independent, representation of <code>t</code> with:</p><ul><li><code>tz_offset_s</code> hints the time zone offset to use. The hint is ignored in the following cases: if <code>tz_offset_s</code> is not an integral number of minutes and its magnitude not in the range permitted by the standard, if <code>add_span t (Span.of_int_s tz_offset_s)</code> is <code>None</code>. If either the hint is ignored or <code>tz_offset_s</code> is unspecified then RFC 3339's <a href="https://tools.ietf.org/html/rfc3339#section-4.3">unknown local offset convention</a> is used to render the time zone component.</li><li><code>frac_s</code> clipped to the range [<code>0</code>;<code>12</code>] specifies that exactly <code>frac_s</code> decimal digits of the fractional second of <code>t</code> are rendered (defaults to <code>0</code>).</li></ul><p><b>Note.</b> The output of this function is similar to but <b>not</b> compliant with RFC 3339, it should only be used for presentation, not as a serialization format.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-pp"><a href="#val-pp" class="anchor"></a><code><span><span class="keyword">val</span> pp : <span><a href="../../ocaml/Stdlib/Format/index.html#type-formatter">Stdlib.Format.formatter</a> <span class="arrow">&#45;&gt;</span></span> <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> unit</span></code></div><div class="spec-doc"><p><code>pp</code> is <code>pp_human ~tz_offset_s:0</code>.</p></div></div><div class="odoc-spec"><div class="spec value anchored" id="val-dump"><a href="#val-dump" class="anchor"></a><code><span><span class="keyword">val</span> dump : <span><a href="../../ocaml/Stdlib/Format/index.html#type-formatter">Stdlib.Format.formatter</a> <span class="arrow">&#45;&gt;</span></span> <span><a href="#type-t">t</a> <span class="arrow">&#45;&gt;</span></span> unit</span></code></div><div class="spec-doc"><p><code>dump ppf t</code> prints an unspecified raw representation of <code>t</code> on <code>ppf</code>.</p></div></div><h2 id="basics"><a href="#basics" class="anchor"></a>Basics</h2><p>POSIX time counts POSIX seconds since the epoch 1970-01-01 00:00:00 UTC. As such a POSIX timestamp is <b>always</b> on the UTC timeline.</p><p>POSIX time doesn't count leap seconds, so by definition it cannot represent them. One way of viewing this is that whenever a leap second is added a POSIX second lasts two SI seconds and whenever a leap second is subtracted a POSIX second lasts zero SI second.</p><p><a href="#"><code>Ptime</code></a> does not provide any mean to convert the duration between two POSIX timestamps to SI seconds. The reason is that in order to accurately find this number, a <a href="http://www.ietf.org/timezones/data/leap-seconds.list">leap second table</a> is needed. However since this table may change every six months, <a href="#"><code>Ptime</code></a> decides not to include it so as not to potentially become incorrect every six months.</p><p>This decision has the following implications. First it should be realised that the durations mentioned by the <a href="#val-add_span"><code>add_span</code></a>, <a href="#val-sub_span"><code>sub_span</code></a> and <a href="#val-diff"><code>diff</code></a> functions are expressed in <em>POSIX seconds</em> which may represent zero, one, or two SI seconds. For example if we add 1 second with <a href="#val-add_span"><code>add_span</code></a> to the POSIX timestamp for 1998-12-31 23:59:59 UTC, what we get is the timestamp for 1999-01-01 00:00:00 UTC:</p><pre class="language-ocaml"><code>let get = function None -&gt; assert false | Some v -&gt; v
let utc d t = get @@ Ptime.of_date_time (d, (t, 0))
let t0 = utc (1998, 12, 31) (23, 59, 59)
let t1 = utc (1999, 01, 01) (00, 00, 00)
let one_s = Ptime.Span.of_int_s 1
let () = assert (Ptime.equal (get @@ Ptime.add_span t0 one_s) t1)</code></pre><p>However since the leap second 1998-12-31 23:59:60 UTC exists, <em>two</em> actual SI seconds elapsed between <code>t0</code> and <code>t1</code>. Now if we use <a href="#val-diff"><code>diff</code></a> to find the POSIX duration that elapsed between <code>t0</code> and <code>t1</code> we get one POSIX second:</p><pre class="language-ocaml"><code>let () = assert (Ptime.Span.equal (Ptime.diff t1 t0) one_s)</code></pre><p>But still, two SI seconds elapsed between these two points in time. Note also that no value of type <a href="#type-t"><code>t</code></a> can represent the UTC timetamp 1998-12-31 23:59:60 and hence <a href="#val-to_date_time"><code>Ptime.to_date_time</code></a> will never return a date-time with a seconds value of <code>60</code>. In fact both 1998-12-31 23:59:60 UTC and 1999-01-01 00:00:00 UTC are represented by the same timestamp:</p><pre class="language-ocaml"><code>let t2 = utc (1998, 12, 31) (23, 59, 60)
let () = assert (Ptime.equal t1 t2)</code></pre><p>This is true of any added leap second, we map it on the first second of the next minute, thus matching the behaviour of POSIX's <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/mktime.html">mktime</a> function.</p><p>If a leap second is subtracted on a day the following occurs 2015, as of writing this never happened. Let YYYY-06-30 23:59:58 be the instant a leap second is subtracted, this means that the next UTC date-time, one SI second later, is YYYY-07-01 00:00:00. However if we diff the two instants:</p><pre class="language-ocaml"><code>let y = 9999 (* hypothetical year were this happens *)
let t0 = utc (y, 06, 30) (23, 59, 58)
let t1 = utc (y, 07, 01) (00, 00, 00)
let two_s = Ptime.Span.of_int_s 2
let () = assert (Ptime.Span.equal (Ptime.diff t1 t0) two_s)</code></pre><p>We get two POSIX seconds, but only one SI second elapsed between these two points in time. It should also be noted that POSIX time will represent a point that never existed in time namely YYYY-06-30 23:59:59, the POSIX second with 0 SI second duration and that <a href="#val-to_date_time"><code>Ptime.to_date_time</code></a> will return a date-time value for this timestamp even though it never existed:</p><pre class="language-ocaml"><code>let t2 = utc (y, 06, 30) (23, 59, 59)
let () = assert (Ptime.equal (get @@ Ptime.add_span t0 one_s) t2)</code></pre><h2 id="notes"><a href="#notes" class="anchor"></a>Notes and limitations</h2><p>The following points should be taken into account</p><ul><li><a href="#"><code>Ptime</code></a> is not a calendar library and will never be.</li><li><a href="#"><code>Ptime</code></a> can only represent picosecond precision timestamps in the range [<a href="#val-min"><code>Ptime.min</code></a>;<a href="#val-max"><code>Ptime.max</code></a>]. It is however able to convert <em>any</em> of these timestamps to a valid date-time or RFC 3339 timestamp.</li><li><p>POSIX time in general is ill-suited to measure wall-clock time spans for the following reasons.</p><ul><li>POSIX time counts time in POSIX seconds. POSIX seconds can represent 2, 1 or 0 SI seconds. <code>Ptime</code> offers no mechanism to determine the SI duration between two timestamps, see the <a href="#basics" title="basics">basics</a>.</li><li>The POSIX timestamps returned by your platform are not monotonic: they are subject to operating system time adjustements and can even go back in time. If you need to measure time spans in a single program run use a monotonic time source (e.g. <code>Mtime</code>).</li></ul></li></ul></div></body></html>