Merge pull request #11424 from lafirest/fix/epoch_maximum_val
fix(datetime): make sure the epoch is not larger than the maximum supported value
This commit is contained in:
commit
b8d3dcf59a
|
@ -38,6 +38,12 @@
|
||||||
-typerefl_from_string({epoch_second/0, ?MODULE, to_epoch_second}).
|
-typerefl_from_string({epoch_second/0, ?MODULE, to_epoch_second}).
|
||||||
-typerefl_from_string({epoch_millisecond/0, ?MODULE, to_epoch_millisecond}).
|
-typerefl_from_string({epoch_millisecond/0, ?MODULE, to_epoch_millisecond}).
|
||||||
|
|
||||||
|
%% the maximum value is the SECONDS_FROM_0_TO_10000 in the calendar.erl,
|
||||||
|
%% here minus SECONDS_PER_DAY to tolerate timezone time offset,
|
||||||
|
%% so the maximum date can reach 9999-12-31 which is ample.
|
||||||
|
-define(MAXIMUM_EPOCH, 253402214400).
|
||||||
|
-define(MAXIMUM_EPOCH_MILLI, 253402214400_000).
|
||||||
|
|
||||||
to_epoch_second(DateTime) ->
|
to_epoch_second(DateTime) ->
|
||||||
to_epoch(DateTime, second).
|
to_epoch(DateTime, second).
|
||||||
|
|
||||||
|
@ -47,8 +53,7 @@ to_epoch_millisecond(DateTime) ->
|
||||||
to_epoch(DateTime, Unit) ->
|
to_epoch(DateTime, Unit) ->
|
||||||
try
|
try
|
||||||
case string:to_integer(DateTime) of
|
case string:to_integer(DateTime) of
|
||||||
{Epoch, []} when Epoch >= 0 -> {ok, Epoch};
|
{Epoch, []} -> validate_epoch(Epoch, Unit);
|
||||||
{_Epoch, []} -> {error, bad_epoch};
|
|
||||||
_ -> {ok, calendar:rfc3339_to_system_time(DateTime, [{unit, Unit}])}
|
_ -> {ok, calendar:rfc3339_to_system_time(DateTime, [{unit, Unit}])}
|
||||||
end
|
end
|
||||||
catch
|
catch
|
||||||
|
@ -71,6 +76,15 @@ human_readable_duration_string(Milliseconds) ->
|
||||||
L2 = lists:map(fun({Time, Unit}) -> [integer_to_list(Time), Unit] end, L1),
|
L2 = lists:map(fun({Time, Unit}) -> [integer_to_list(Time), Unit] end, L1),
|
||||||
lists:flatten(lists:join(", ", L2)).
|
lists:flatten(lists:join(", ", L2)).
|
||||||
|
|
||||||
|
validate_epoch(Epoch, _Unit) when Epoch < 0 ->
|
||||||
|
{error, bad_epoch};
|
||||||
|
validate_epoch(Epoch, second) when Epoch =< ?MAXIMUM_EPOCH ->
|
||||||
|
{ok, Epoch};
|
||||||
|
validate_epoch(Epoch, millisecond) when Epoch =< ?MAXIMUM_EPOCH_MILLI ->
|
||||||
|
{ok, Epoch};
|
||||||
|
validate_epoch(_Epoch, _Unit) ->
|
||||||
|
{error, bad_epoch}.
|
||||||
|
|
||||||
-ifdef(TEST).
|
-ifdef(TEST).
|
||||||
-include_lib("eunit/include/eunit.hrl").
|
-include_lib("eunit/include/eunit.hrl").
|
||||||
-compile(nowarn_export_all).
|
-compile(nowarn_export_all).
|
||||||
|
@ -90,9 +104,11 @@ fields(bar) ->
|
||||||
).
|
).
|
||||||
|
|
||||||
epoch_ok_test() ->
|
epoch_ok_test() ->
|
||||||
|
BigStamp = 1 bsl 37,
|
||||||
Args = [
|
Args = [
|
||||||
{0, 0, 0, 0},
|
{0, 0, 0, 0},
|
||||||
{1, 1, 1, 1},
|
{1, 1, 1, 1},
|
||||||
|
{BigStamp, BigStamp * 1000, BigStamp, BigStamp * 1000},
|
||||||
{"2022-01-01T08:00:00+08:00", "2022-01-01T08:00:00+08:00", 1640995200, 1640995200000}
|
{"2022-01-01T08:00:00+08:00", "2022-01-01T08:00:00+08:00", 1640995200, 1640995200000}
|
||||||
],
|
],
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
|
@ -112,9 +128,12 @@ check_ok(Input, Sec, Ms) ->
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
epoch_failed_test() ->
|
epoch_failed_test() ->
|
||||||
|
BigStamp = 1 bsl 38,
|
||||||
Args = [
|
Args = [
|
||||||
{-1, -1},
|
{-1, -1},
|
||||||
{"1s", "1s"},
|
{"1s", "1s"},
|
||||||
|
{BigStamp, 0},
|
||||||
|
{0, BigStamp * 1000},
|
||||||
{"2022-13-13T08:00:00+08:00", "2022-13-13T08:00:00+08:00"}
|
{"2022-13-13T08:00:00+08:00", "2022-13-13T08:00:00+08:00"}
|
||||||
],
|
],
|
||||||
lists:foreach(
|
lists:foreach(
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Add a check for the maximum value of the timestamp in the API to ensure it is a valid Unix timestamp.
|
Loading…
Reference in New Issue