/home/runner/work/klsn/klsn/_build/test/cover/eunit/klsn_time.html

1 %% @doc
2 %% Time conversion utilities between RFC3339 datetimes and Unix time
3 %% (seconds/nanoseconds). This module:
4 %%
5 %% - Accepts RFC3339 datetimes as UTF-8 binaries (e.g. <<"1970-01-01T00:00:00Z">>).
6 %% - Produces RFC3339 binaries using a fixed offset of "+09:00" for
7 %% unix_seconds_to_rfc3339/1 and unix_nanoseconds_to_rfc3339/1.
8 %% - Supports timestamps before and after the Unix epoch.
9 %% - Uses the runtime's calendar and erlang:convert_time_unit/3 for
10 %% correctness and performance.
11 %%
12 %% Notes on offsets and negativity:
13 %% - When parsing RFC3339 (the rfc3339_to_* functions), any explicit offset
14 %% in the input is honored; the returned Unix time is always relative to UTC.
15 %% - For negative nanoseconds to seconds conversion, erlang:convert_time_unit/3
16 %% follows floor semantics (rounding toward negative infinity). For example,
17 %% -1 ns -> -1 s, and -1999999999 ns -> -2 s.
18 %%
19 %% @see rfc3339_to_unix_seconds/1
20 %% @see rfc3339_to_unix_nanoseconds/1
21 %% @see unix_seconds_to_rfc3339/1
22 %% @see unix_nanoseconds_to_rfc3339/1
23 %% @see unix_seconds_to_unix_nanoseconds/1
24 %% @see unix_nanoseconds_to_unix_seconds/1
25 -module(klsn_time).
26
27 -export([
28 rfc3339_to_unix_seconds/1
29 , rfc3339_to_unix_nanoseconds/1
30 , unix_seconds_to_rfc3339/1
31 , unix_nanoseconds_to_rfc3339/1
32 , unix_seconds_to_unix_nanoseconds/1
33 , unix_nanoseconds_to_unix_seconds/1
34 ]).
35
36 -export_type([
37 rfc3339/0
38 , unix_seconds/0
39 , unix_nanoseconds/0
40 ]).
41
42 -type rfc3339() :: unicode:unicode_binary().
43 -type unix_seconds() :: integer().
44 -type unix_nanoseconds() :: integer().
45
46
47 %% @doc
48 %% Convert an RFC3339 datetime (binary) to Unix time (seconds since epoch).
49 %%
50 %% The input may include a timezone designator (e.g. Z, +09:00, -05:00).
51 %% The returned integer is the UTC Unix timestamp in seconds.
52 %%
53 %% Example:
54 %% <pre>
55 %% 1> klsn_time:rfc3339_to_unix_seconds(&lt;&lt;"1970-01-01T00:00:00Z"&gt;&gt;).
56 %% 0
57 %% 2> klsn_time:rfc3339_to_unix_seconds(&lt;&lt;"1970-01-01T09:00:00+09:00"&gt;&gt;).
58 %% 0
59 %% </pre>
60 -spec rfc3339_to_unix_seconds(rfc3339()) -> unix_seconds().
61 rfc3339_to_unix_seconds(RFC3339) when is_binary(RFC3339) ->
62 5 String = binary_to_list(RFC3339),
63 5 calendar:rfc3339_to_system_time(String, [{unit, second}]).
64
65 %% @doc
66 %% Convert an RFC3339 datetime (binary) to Unix time (nanoseconds since epoch).
67 %%
68 %% Fractional seconds in the input are supported up to nanosecond precision.
69 %% The returned integer is the UTC Unix timestamp in nanoseconds.
70 %%
71 %% Example:
72 %% <pre>
73 %% 1> klsn_time:rfc3339_to_unix_nanoseconds(&lt;&lt;"1970-01-01T00:00:00.123456789Z"&gt;&gt;).
74 %% 123456789
75 %% 2> klsn_time:rfc3339_to_unix_nanoseconds(&lt;&lt;"1970-01-01T08:59:59.500000000+09:00"&gt;&gt;).
76 %% -1500000000
77 %% </pre>
78 -spec rfc3339_to_unix_nanoseconds(rfc3339()) -> unix_nanoseconds().
79 rfc3339_to_unix_nanoseconds(RFC3339) when is_binary(RFC3339) ->
80 8 String = binary_to_list(RFC3339),
81 8 calendar:rfc3339_to_system_time(String, [{unit, nanosecond}]).
82
83 %% @doc
84 %% Convert Unix time in seconds to RFC3339 datetime (binary).
85 %%
86 %% The returned RFC3339 string uses the fixed offset "+09:00".
87 %%
88 %% Example:
89 %% <pre>
90 %% 1> klsn_time:unix_seconds_to_rfc3339(0).
91 %% &lt;&lt;"1970-01-01T09:00:00+09:00"&gt;&gt;
92 %% </pre>
93 -spec unix_seconds_to_rfc3339(unix_seconds()) -> rfc3339().
94 unix_seconds_to_rfc3339(Seconds) when is_integer(Seconds) ->
95 3 iolist_to_binary(calendar:system_time_to_rfc3339(Seconds, [{unit, second}, {offset, "+09:00"}])).
96
97 %% @doc
98 %% Convert Unix time in nanoseconds to RFC3339 datetime (binary).
99 %%
100 %% The returned RFC3339 string uses the fixed offset "+09:00" and includes a
101 %% nanosecond fractional component (e.g. ".000000000").
102 %%
103 %% Example:
104 %% <pre>
105 %% 1> klsn_time:unix_nanoseconds_to_rfc3339(0).
106 %% &lt;&lt;"1970-01-01T09:00:00.000000000+09:00"&gt;&gt;
107 %% </pre>
108 -spec unix_nanoseconds_to_rfc3339(unix_nanoseconds()) -> rfc3339().
109 unix_nanoseconds_to_rfc3339(Nanoseconds) when is_integer(Nanoseconds) ->
110 4 iolist_to_binary(calendar:system_time_to_rfc3339(Nanoseconds, [{unit, nanosecond}, {offset, "+09:00"}])).
111
112 %% @doc
113 %% Convert Unix time from seconds to nanoseconds.
114 %%
115 %% This is an exact integer multiplication (1 s = 1,000,000,000 ns).
116 %%
117 %% Example:
118 %% <pre>
119 %% 1> klsn_time:unix_seconds_to_unix_nanoseconds(-1).
120 %% -1000000000
121 %% </pre>
122 -spec unix_seconds_to_unix_nanoseconds(unix_seconds()) -> unix_nanoseconds().
123 unix_seconds_to_unix_nanoseconds(Seconds) when is_integer(Seconds) ->
124 3 erlang:convert_time_unit(Seconds, second, nanosecond).
125
126 %% @doc
127 %% Convert Unix time from nanoseconds to seconds.
128 %%
129 %% Uses the runtime's floor semantics for negative values
130 %% (rounding toward negative infinity).
131 %%
132 %% Examples:
133 %% <pre>
134 %% 1> klsn_time:unix_nanoseconds_to_unix_seconds(1999999999).
135 %% 1
136 %% 2> klsn_time:unix_nanoseconds_to_unix_seconds(-1).
137 %% -1
138 %% 3> klsn_time:unix_nanoseconds_to_unix_seconds(-1999999999).
139 %% -2
140 %% </pre>
141 -spec unix_nanoseconds_to_unix_seconds(unix_nanoseconds()) -> unix_seconds().
142 unix_nanoseconds_to_unix_seconds(Nanoseconds) when is_integer(Nanoseconds) ->
143 5 erlang:convert_time_unit(Nanoseconds, nanosecond, second).
Line Hits Source