Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 26 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -278,8 +278,11 @@ see below | `datetime()`

erlang datetime tuples (`{{Year, Month, Day}, {Hour, Min, Sec}}`) as returned
from `erlang:localtime/0` are automatically encoded as [iso8601][iso8601]
strings and are assumed to be UTC time. no conversion is attempted of json [iso8601][iso8601] strings in decoded json

strings and are assumed to be UTC time. no conversion is attempted of json [iso8601][iso8601] strings in decoded json.
If you want use other format in the output of the datetime value use in the config options [{format_date, {Format, Order}}],
where Format is a string representing the format that the datetime will be printed and order is the order of the values to be
printed, example: `[{format_date, {"~2..0w-~2..0w-~4..0w ~2..0w:~2..0w:~2..0w", [month, day, year, hour, minute, second]}}])`,
this will print: `"01-20-2016 17:38:59"`. The Order only supports [ month, day, year, hour, minute, second ] list.

### incomplete input ###

Expand Down Expand Up @@ -370,12 +373,24 @@ option() = dirty_strings
| return_tail
| uescape
| unescaped_jsonp
| {format_date, {format_option(), order()}}

strict_option() = comments
| trailing_commas
| utf8
| single_quotes
| escapes

format_option() = string()

order() = [ order_option(),... ]

order_option() = year
| month
| day
| hour
| minute
| second
```

**jsx** functions all take a common set of options. not all flags have meaning
Expand Down Expand Up @@ -467,6 +482,15 @@ additional options beyond these. see
these codepoints are escaped (to `\u2028` and `\u2029`, respectively) to
retain compatibility. this option simply removes that escaping

- `format_date`

As mentioned above if you want use other format in the output of the datetime value
use in the config options `[{format_date, {Format, Order}}]`,
where `Format` is a string representing the format that the datetime will be printed
and `Order` is the order of the values to be printed, example:
`[{format_date, {"~2..0w-~2..0w-~4..0w ~2..0w:~2..0w:~2..0w", [month, day, year, hour, minute, second]}}])`,
this will print: `"01-20-2016 17:38:59"`.
The Order only supports [ month, day, year, hour, minute, second ] list.

## exports ##

Expand Down
7 changes: 5 additions & 2 deletions src/jsx_config.erl
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ parse_config([multi_term|Rest], Config) ->
parse_config(Rest, Config#config{multi_term=true});
parse_config([return_tail|Rest], Config) ->
parse_config(Rest, Config#config{return_tail=true});
parse_config([{format_date, Format}|Rest], Config) ->
parse_config(Rest, Config#config{format_date=Format});
%% retained for backwards compat, now does nothing however
parse_config([repeat_keys|Rest], Config) ->
parse_config(Rest, Config);
Expand Down Expand Up @@ -125,7 +127,7 @@ config_to_list(Config) ->
({Key, true}) -> Key
end,
lists:filter(
fun({_, false}) -> false; (_) -> true end,
fun({_, false}) -> false; ({_, X}) when is_list(X) -> X; (_) -> true end,
lists:zip(record_info(fields, config), tl(tuple_to_list(Config)))
)
)).
Expand Down Expand Up @@ -168,7 +170,8 @@ valid_flags() ->
stream,
uescape,
error_handler,
incomplete_handler
incomplete_handler,
format_date
].


Expand Down
3 changes: 2 additions & 1 deletion src/jsx_config.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@
uescape = false :: boolean(),
unescaped_jsonp = false :: boolean(),
error_handler = false :: false | jsx_config:handler(),
incomplete_handler = false :: false | jsx_config:handler()
incomplete_handler = false :: false | jsx_config:handler(),
format_date = false :: false
}).
53 changes: 47 additions & 6 deletions src/jsx_parser.erl
Original file line number Diff line number Diff line change
Expand Up @@ -112,29 +112,42 @@ value([{raw, Raw}|Tokens], Handler, Stack, Config) when is_binary(Raw) ->
value([{_,_,_}=Timestamp|Tokens], Handler, Stack, Config) ->
{{Year, Month, Day}, {Hour, Min, Sec}} = calendar:now_to_datetime(
Timestamp),
% In case of specify format for date
{Format, Order} = case Config#config.format_date of
false -> {"~4.10.0B-~2.10.0B-~2.10.0BT~2.10.0B:~2.10.0B:~2.10.0BZ", []};
X -> X
end,
value([{string, unicode:characters_to_binary(io_lib:format(
"~4.10.0B-~2.10.0B-~2.10.0BT~2.10.0B:~2.10.0B:~2.10.0BZ",
[Year, Month, Day, Hour, Min, Sec]
Format, formatting_date(Order, [Year, Month, Day, Hour, Min, Sec])
))}|Tokens],
Handler,
Stack,
Config
);
value([{{Year, Month, Day}, {Hour, Min, Sec}}|Tokens], Handler, Stack, Config)
when is_integer(Year), is_integer(Month), is_integer(Day), is_integer(Hour), is_integer(Min), is_integer(Sec) ->
% In case of specify format for date
{Format, Order} = case Config#config.format_date of
false -> {"~4.10.0B-~2.10.0B-~2.10.0BT~2.10.0B:~2.10.0B:~2.10.0BZ", []};
X -> X
end,
value([{string, unicode:characters_to_binary(io_lib:format(
"~4.10.0B-~2.10.0B-~2.10.0BT~2.10.0B:~2.10.0B:~2.10.0BZ",
[Year, Month, Day, Hour, Min, Sec]
Format, formatting_date(Order, [Year, Month, Day, Hour, Min, Sec])
))}|Tokens],
Handler,
Stack,
Config
);
value([{{Year, Month, Day}, {Hour, Min, Sec}}|Tokens], Handler, Stack, Config)
when is_integer(Year), is_integer(Month), is_integer(Day), is_integer(Hour), is_integer(Min), is_float(Sec) ->
% In case of specify format for date
{Format, Order} = case Config#config.format_date of
false -> {"~4.10.0B-~2.10.0B-~2.10.0BT~2.10.0B:~2.10.0B:~9.6.0fZ", []};
X -> X
end,

value([{string, unicode:characters_to_binary(io_lib:format(
"~4.10.0B-~2.10.0B-~2.10.0BT~2.10.0B:~2.10.0B:~9.6.0fZ",
[Year, Month, Day, Hour, Min, Sec]
Format, formatting_date(Order, [Year, Month, Day, Hour, Min, Sec])
))}|Tokens],
Handler,
Stack,
Expand Down Expand Up @@ -629,6 +642,34 @@ to_hex(15) -> $f;
to_hex(X) -> X + 48. %% ascii "1" is [49], "2" is [50], etc...


% extract format of date
formatting_date([], Numbers) ->
Numbers;
formatting_date(Formats, Numbers) ->
Formats0 = [ {F, 0} || F <- Formats ],
formatting_date(Formats0, Formats0, Numbers).

formatting_date(Formats, [], _) ->
[ V || {_, V} <- Formats ];
formatting_date(Formats, [{year, 0}|Rest], Numbers) ->
formatting_date(lists:keyreplace(year, 1,
Formats, {year, lists:nth(1, Numbers)}), Rest, Numbers);
formatting_date(Formats, [{month, 0}|Rest], Numbers) ->
formatting_date(lists:keyreplace(month, 1,
Formats, {month, lists:nth(2, Numbers)}), Rest, Numbers);
formatting_date(Formats, [{day, 0}|Rest], Numbers) ->
formatting_date(lists:keyreplace(day, 1,
Formats, {day, lists:nth(3, Numbers)}), Rest, Numbers);
formatting_date(Formats, [{hour, 0}|Rest], Numbers) ->
formatting_date(lists:keyreplace(hour, 1,
Formats, {hour, lists:nth(4, Numbers)}), Rest, Numbers);
formatting_date(Formats, [{minute, 0}|Rest], Numbers) ->
formatting_date(lists:keyreplace(minute, 1,
Formats, {minute, lists:nth(5, Numbers)}), Rest, Numbers);
formatting_date(Formats, [{second, 0}|Rest], Numbers) ->
formatting_date(lists:keyreplace(second, 1,
Formats, {second, lists:nth(6, Numbers)}), Rest, Numbers).

%% for raw input
-spec init(proplists:proplist()) -> list().

Expand Down