From dfcf770f166073e3b6113edb36c9c01e616ee702 Mon Sep 17 00:00:00 2001 From: Leonard Boyce Date: Tue, 10 Oct 2023 14:37:50 -0400 Subject: [PATCH] (feat) Erlang date() and datetime() encoders --- src/thoas.erl | 4 +++- src/thoas_encode.erl | 27 ++++++++++++++++++++++++++- test/thoas_encode_test.erl | 11 +++++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/thoas.erl b/src/thoas.erl index f8ad848..0077783 100644 --- a/src/thoas.erl +++ b/src/thoas.erl @@ -27,11 +27,13 @@ list(json_term()) | #{ binary() => json_term() }. --type input_term() :: +-type input_term() :: integer() | float() | binary() | atom() | + calendar:date_time() | + calendar:date() | list(input_term()) | list({binary() | atom(), input_term()}) | #{ binary() | atom() => input_term() }. diff --git a/src/thoas_encode.erl b/src/thoas_encode.erl index 1d48a57..f2fbbef 100644 --- a/src/thoas_encode.erl +++ b/src/thoas_encode.erl @@ -1727,6 +1727,32 @@ value(Value, _Escape) when is_float(Value) -> float(Value); value([{_, _} | _] = Keyword, Escape) -> map_naive(Keyword, Escape); +value({Y, M, D}, Escape) + when is_integer(Y) andalso Y >= 0 andalso Y =< 9999 andalso + is_integer(M) andalso M >= 1 andalso M =< 12 andalso + is_integer(D) andalso D >= 1 andalso D =< 31 -> + DateTime = io_lib:format("~4..0b-~2..0b-~2..0b", [Y, M, D]), + encode_string(iolist_to_binary(DateTime), Escape); +value({{Y, M, D}, {H, I, S}}, Escape) + when is_integer(Y) andalso Y >= 0 andalso Y =< 9999 andalso + is_integer(M) andalso M >= 1 andalso M =< 12 andalso + is_integer(D) andalso D >= 1 andalso D =< 31 andalso + is_integer(H) andalso H >= 0 andalso H =< 23 andalso + is_integer(I) andalso I >= 0 andalso I =< 59 andalso + is_integer(S) andalso S >= 0 andalso S =< 59 -> + Dt = io_lib:format("~4..0b-~2..0b-~2..0bT~2..0b:~2..0b:~sZ", + [Y, M, D, H, I, integer_to_list(S)]), + encode_string(iolist_to_binary(Dt), Escape); +value({{Y, M, D}, {H, I, S}}, Escape) + when is_integer(Y) andalso Y >= 0 andalso Y =< 9999 andalso + is_integer(M) andalso M >= 1 andalso M =< 12 andalso + is_integer(D) andalso D >= 1 andalso D =< 31 andalso + is_integer(H) andalso H >= 0 andalso H =< 23 andalso + is_integer(I) andalso I >= 0 andalso I =< 59 andalso + is_float(S) andalso S >= 0 andalso S < 60 -> + Dt = io_lib:format("~4..0b-~2..0b-~2..0bT~2..0b:~2..0b:~sZ", + [Y, M, D, H, I, float_to_binary(S, [short])]), + encode_string(iolist_to_binary(Dt), Escape); value(Value, Escape) when is_list(Value) -> list(Value, Escape); value(Value, Escape) when is_map(Value) -> @@ -1736,4 +1762,3 @@ value(Value, Escape) when is_map(Value) -> Keyword -> map_naive(Keyword, Escape) end. - diff --git a/test/thoas_encode_test.erl b/test/thoas_encode_test.erl index e12c390..079eb86 100644 --- a/test/thoas_encode_test.erl +++ b/test/thoas_encode_test.erl @@ -118,3 +118,14 @@ encode_test_() -> ?_assertEqual(Expected, iolist_to_binary(encode(Input, #{}))) || {Input, Expected} <- Cases ]. + +types_test_() -> + Cases =[ + {#{<<"date">> => {2023,8,7}}, <<"{\"date\":\"2023-08-07\"}">>}, + {#{<<"datetime">> => {{2023,8,7},{19,2,24}}}, <<"{\"datetime\":\"2023-08-07T19:02:24Z\"}">>}, + {#{<<"datetime">> => {{2023,8,7},{19,2,24.65432}}}, <<"{\"datetime\":\"2023-08-07T19:02:24.65432Z\"}">>} + ], + [ + ?_assertEqual(Expected, iolist_to_binary(encode(Input, #{}))) + || {Input, Expected} <- Cases + ].