File 2081-stdlib-Add-native-to-calendar-rfc3339_time_unit.patch of Package erlang
From 93226c07471c11bed1ced88cdc016abbc7f7e594 Mon Sep 17 00:00:00 2001
From: Sverker Eriksson <sverker@erlang.org>
Date: Fri, 24 Sep 2021 20:10:56 +0200
Subject: [PATCH 1/2] stdlib: Add native to calendar rfc3339_time_unit
thus supporting
calendar:system_time_to_rfc3339(Time, [{unit,native}]).
calendar:rfc3339_to_system_time(Time, [{unit,native}]).
---
lib/stdlib/doc/src/calendar.xml | 18 ++++++++++++------
lib/stdlib/src/calendar.erl | 25 +++++++++++++++++++++----
lib/stdlib/test/calendar_SUITE.erl | 18 +++++++++++++++++-
3 files changed, 50 insertions(+), 11 deletions(-)
diff --git a/lib/stdlib/doc/src/calendar.xml b/lib/stdlib/doc/src/calendar.xml
index 213bca365d..feb0a5784e 100644
--- a/lib/stdlib/doc/src/calendar.xml
+++ b/lib/stdlib/doc/src/calendar.xml
@@ -124,6 +124,13 @@
<datatype>
<name name="weeknum"/>
</datatype>
+ <datatype>
+ <name name="rfc3339_time_unit"/>
+ <desc><note><p>
+ The <c>native</c> time unit was added to <c>rfc3339_time_unit()</c>
+ in OTP 25.0.</p></note>
+ </desc>
+ </datatype>
</datatypes>
<funcs>
@@ -321,7 +328,6 @@
<name name="rfc3339_to_system_time" arity="2" since="OTP 21.0"/>
<fsummary>Convert from RFC 3339 timestamp to system time.</fsummary>
<type name="rfc3339_string"/>
- <type name="rfc3339_time_unit"/>
<desc>
<p>Converts an RFC 3339 timestamp into system time. The data format
of RFC 3339 timestamps is described by
@@ -378,7 +384,6 @@
<fsummary>Convert from system to RFC 3339 timestamp.</fsummary>
<type name="offset"/>
<type name="rfc3339_string"/>
- <type name="rfc3339_time_unit"/>
<desc>
<p>Converts a system time into an RFC 3339 timestamp. The data format
of RFC 3339 timestamps is described by
@@ -401,12 +406,13 @@
<tag><c>{unit, Unit}</c></tag>
<item><p>The time unit of <c><anno>Time</anno></c>. The
default is <c>second</c>. If some other unit is given
- (<c>millisecond</c>, <c>microsecond</c>, or
- <c>nanosecond</c>), the formatted string includes a
+ (<c>millisecond</c>, <c>microsecond</c>, <c>nanosecond</c>, or
+ <c>native</c>), the formatted string includes a
fraction of a second. The number of fractional second
digits is three, six, or nine depending on what time unit
- is chosen. Notice that trailing zeros are not removed from
- the fraction.
+ is chosen. For <c>native</c> three fractional digits are
+ included. Notice that trailing zeros are not removed from the
+ fraction.
</p>
</item>
</taglist>
diff --git a/lib/stdlib/src/calendar.erl b/lib/stdlib/src/calendar.erl
index 2f95f54312..e9fcccaba8 100644
--- a/lib/stdlib/src/calendar.erl
+++ b/lib/stdlib/src/calendar.erl
@@ -94,11 +94,11 @@
-type yearweeknum() :: {year(),weeknum()}.
-type rfc3339_string() :: [byte(), ...].
-%% By design 'native' is not supported:
-type rfc3339_time_unit() :: 'microsecond'
| 'millisecond'
| 'nanosecond'
- | 'second'.
+ | 'second'
+ | 'native'.
%%----------------------------------------------------------------------
@@ -444,7 +444,23 @@ system_time_to_rfc3339(Time) ->
system_time_to_rfc3339(Time, Options) ->
Unit = proplists:get_value(unit, Options, second),
- OffsetOption = proplists:get_value(offset, Options, ""),
+ OffsetOpt0 = proplists:get_value(offset, Options, ""),
+ case Unit of
+ native ->
+ TimeMS = erlang:convert_time_unit(Time, native, millisecond),
+ OffsetOpt1 =
+ if is_integer(OffsetOpt0) ->
+ erlang:convert_time_unit(OffsetOpt0, native,
+ millisecond);
+ true ->
+ OffsetOpt0
+ end,
+ system_time_to_rfc3339_do(TimeMS, Options, millisecond, OffsetOpt1);
+ _ ->
+ system_time_to_rfc3339_do(Time, Options, Unit, OffsetOpt0)
+ end.
+
+system_time_to_rfc3339_do(Time, Options, Unit, OffsetOption) ->
T = proplists:get_value(time_designator, Options, $T),
AdjustmentSecs = offset_adjustment(Time, Unit, OffsetOption),
Offset = offset(OffsetOption, AdjustmentSecs),
@@ -739,7 +755,8 @@ copy_sign(N1, _N2) -> N1.
factor(second) -> 1;
factor(millisecond) -> 1000;
factor(microsecond) -> 1000000;
-factor(nanosecond) -> 1000000000.
+factor(nanosecond) -> 1000000000;
+factor(native) -> erlang:convert_time_unit(1, second, native).
log10(1000) -> 3;
log10(1000000) -> 6;
diff --git a/lib/stdlib/test/calendar_SUITE.erl b/lib/stdlib/test/calendar_SUITE.erl
index bea5a217db..5642852211 100644
--- a/lib/stdlib/test/calendar_SUITE.erl
+++ b/lib/stdlib/test/calendar_SUITE.erl
@@ -192,15 +192,19 @@ rfc3339(Config) when is_list(Config) ->
Mys = [{unit, microsecond}],
Ns = [{unit, nanosecond}],
S = [{unit, second}],
+ Na = [{unit, native}],
D = [{time_designator, $\s}],
Z = [{offset, "Z"}],
"1985-04-12T23:20:50.520Z" = test_parse("1985-04-12T23:20:50.52Z", Ms),
- "1985-04-12T23:20:50.520Z" = test_parse("1985-04-12t23:20:50.52z", Ms),
+ "1985-04-12T23:20:50.520Z" = test_parse("1985-04-12t23:20:50.52z", Na),
"1985-04-12T21:20:50.520Z" =
test_parse("1985-04-12T23:20:50.52+02:00", Ms),
+ "1985-04-12T21:20:50.520Z" =
+ test_parse("1985-04-12T23:20:50.52+02:00", Na),
"1985-04-12T23:20:50Z" = test_parse("1985-04-12T23:20:50.52Z", S),
"1985-04-12T23:20:50.520Z" = test_parse("1985-04-12T23:20:50.52Z", Ms),
+ "1985-04-12T23:20:50.520Z" = test_parse("1985-04-12T23:20:50.52Z", Na),
"1985-04-12T23:20:50.520000Z" =
test_parse("1985-04-12t23:20:50.52z", Mys),
"1985-04-12 21:20:50.520000000Z" =
@@ -216,6 +216,8 @@ rfc3339(Config) when is_list(Config) ->
"9999-12-31T23:59:59Z" = roundtrip_fmt_rfc3339_z(253402300799, []),
"9999-12-31T23:59:59.999Z" = roundtrip_fmt_rfc3339_z(253402300799*1000+999, Ms),
+ NaPerSec = erlang:convert_time_unit(1, second, native),
+ "9999-12-31T23:59:59.999Z" = do_format_z(253402300799*NaPerSec+(NaPerSec-1), Na),
"9999-12-31T23:59:59.999999Z" =
roundtrip_fmt_rfc3339_z(253402300799*1000000+999999, Mys),
"9999-12-31T23:59:59.999999999Z" =
@@ -236,6 +242,7 @@ rfc3339(Config) when is_list(Config) ->
"1970-01-02T00:00:00Z" = test_parse("1970-01-01T23:59:60.5Z"),
"1970-01-02T00:00:00Z" = test_parse("1970-01-01T23:59:60.55Z"),
"1970-01-02T00:00:00.550Z" = test_parse("1970-01-01T23:59:60.55Z", Ms),
+ "1970-01-02T00:00:00.550Z" = test_parse("1970-01-01T23:59:60.55Z", Na),
"1970-01-02T00:00:00.550000Z" =
test_parse("1970-01-01T23:59:60.55Z", Mys),
"1970-01-02T00:00:00.550000000Z" =
@@ -269,16 +276,25 @@ rfc3339(Config) when is_list(Config) ->
"2000-01-01T10:02:00.000000000+00:02" =
do_format(TO * 1000 * 1000 * 1000,
[{offset, 120 * 1000 * 1000 * 1000}]++Ns),
+ "2000-01-01T10:02:00.000+00:02" =
+ do_format(TO * NaPerSec, [{offset, 120 * NaPerSec}]++Na),
+
NStr = "2000-01-01T09:58:00-00:02",
NStr = do_format(TO, [{offset, -120}]),
"2000-01-01T09:58:00.000-00:02" =
do_format(TO * 1000, [{offset, -120 * 1000}]++Ms),
+ "2000-01-01T09:58:00.000-00:02" =
+ do_format(TO * NaPerSec, [{offset, -120 * NaPerSec}]++Na),
"2000-01-01T09:58:00.000000-00:02" =
do_format(TO * 1000 * 1000, [{offset, -120 * 1000 * 1000}]++Mys),
"2000-01-01T09:58:00.000000000-00:02" =
do_format(TO * 1000 * 1000 * 1000,
[{offset, -120 * 1000 * 1000 * 1000}]++Ns),
+ "2000-01-01T09:58:00.000-00:02" =
+ do_format(TO * 1000, [{offset, -120 * 1000}]++Ms),
+ "2000-01-01T09:58:00.000-00:02" =
+ do_format(TO * NaPerSec, [{offset, -120 * NaPerSec}]++Na),
543210000 = do_parse("1970-01-01T00:00:00.54321Z", Ns),
54321000 = do_parse("1970-01-01T00:00:00.054321Z", Ns),
--
2.31.1