From 4585c223b75f33bf4b68c91c5404bce65f58ef1d Mon Sep 17 00:00:00 2001 From: Euen Date: Mon, 22 Aug 2016 17:06:30 -0300 Subject: [PATCH 1/3] Add rebar3 support --- .gitignore | 4 ++++ rebar.config | 55 +++++++++++++++++++++++++++++++++++++++++++++ rebar.lock | 1 + src/iso8601.app.src | 3 ++- src/iso8601.erl | 2 +- 5 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 rebar.config create mode 100644 rebar.lock diff --git a/.gitignore b/.gitignore index 969d006..d095837 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ .eunit ebin +doc +_build +logs +rebar3.crashdump \ No newline at end of file diff --git a/rebar.config b/rebar.config new file mode 100644 index 0000000..dc8ac7c --- /dev/null +++ b/rebar.config @@ -0,0 +1,55 @@ +%% -*- mode: erlang;erlang-indent-level: 2;indent-tabs-mode: nil -*- +%% ex: ts=4 sw=4 ft=erlang et + +%% == Erlang Compiler == + +%% Erlang compiler options +{erl_opts, [ warn_unused_vars + , warn_export_all + , warn_shadow_vars + , warn_unused_import + , warn_unused_function + , warn_bif_clash + , warn_unused_record + , warn_deprecated_function + , warn_obsolete_guard + , strict_validation + , warn_export_vars + , warn_exported_vars + , warn_missing_spec + , warn_untyped_record + , debug_info]}. + +{profiles, [ + {shell, [ + {deps, [ + {sync, {git, "https://github.com/rustyio/sync.git", {ref, "9c78e7b"}}} + ]} + ]} +]}. + +%% == Cover == + +{cover_enabled, true}. + +{cover_opts, [verbose]}. + +%% == Dependencies == + +{deps, []}. + +%% == Dialyzer == + +{dialyzer, [ {warnings, [ no_return + , unmatched_returns + , error_handling + ]} + , {plt_apps, top_level_deps} + , {plt_extra_apps, []} + , {plt_location, local} + , {base_plt_apps, [stdlib, kernel]} + , {base_plt_location, global}]}. + +%% == Shell == + +{shell, [{apps, [sync]}]}. \ No newline at end of file diff --git a/rebar.lock b/rebar.lock new file mode 100644 index 0000000..57afcca --- /dev/null +++ b/rebar.lock @@ -0,0 +1 @@ +[]. diff --git a/src/iso8601.app.src b/src/iso8601.app.src index f94e638..f0d72a1 100644 --- a/src/iso8601.app.src +++ b/src/iso8601.app.src @@ -5,5 +5,6 @@ {registered, []}, {applications, [kernel, stdlib]}, {env, []}, - {modules, []} + {modules, []}, + {build_tools, ["make", "rebar3"]} ]}. diff --git a/src/iso8601.erl b/src/iso8601.erl index a446fc6..e1b1bb0 100644 --- a/src/iso8601.erl +++ b/src/iso8601.erl @@ -32,7 +32,7 @@ %% API -spec now () -> binary(). -%% @doc Wrapper for `iso8601:format(os:timestamp())` +%% @doc Wrapper for `iso8601:format(os:timestamp())' now() -> format(os:timestamp()). From cbaa1042855606a883877d14e9033ce99727d376 Mon Sep 17 00:00:00 2001 From: Euen Date: Mon, 22 Aug 2016 18:37:37 -0300 Subject: [PATCH 2/3] Give support to elvis and dialyzer --- elvis.config | 32 +++++ src/iso8601.erl | 271 +++++++++++++++++++++-------------------- test/iso8601_tests.erl | 107 ++++++++-------- 3 files changed, 228 insertions(+), 182 deletions(-) create mode 100644 elvis.config diff --git a/elvis.config b/elvis.config new file mode 100644 index 0000000..26b00d4 --- /dev/null +++ b/elvis.config @@ -0,0 +1,32 @@ +[ + { + elvis, + [ + {config, + [#{dirs => ["src"], + filter => "*.erl", + rules => [ {elvis_style, dont_repeat_yourself, #{min_complexity => 20}} + , {elvis_style, function_naming_convention, disable} + , {elvis_style, no_if_expression, disable}], + ruleset => erl_files + }, + #{dirs => ["test"], + filter => "*.erl", + rules => [ {elvis_style, macro_names, disable} + , {elvis_style, dont_repeat_yourself, disable} + , {elvis_style, variable_naming_convention, disable}], + ruleset => erl_files + }, + #{dirs => ["."], + filter => "rebar.config", + ruleset => rebar_config + }, + #{dirs => ["."], + filter => "elvis.config", + ruleset => elvis_config + } + ] + } + ] + } +]. \ No newline at end of file diff --git a/src/iso8601.erl b/src/iso8601.erl index a446fc6..a094407 100644 --- a/src/iso8601.erl +++ b/src/iso8601.erl @@ -13,12 +13,12 @@ is_duration/1, is_datetime/1]). --compile({no_auto_import,[now/0]}). +-compile({no_auto_import, [now/0]}). -export_types([datetime/0, timestamp/0]). --define(MIDNIGHT, {0,0,0}). +-define(MIDNIGHT, {0, 0, 0}). -define(V, proplists:get_value). -type datetime() :: {Date::calendar:date(), @@ -36,45 +36,46 @@ now() -> format(os:timestamp()). --spec add_time (datetime() | timestamp(), integer(), integer(), integer()) -> datetime(). +-spec add_time (datetime() | timestamp(), integer(), integer(), integer()) -> + datetime(). %% @doc Add some time to the supplied `datetime()'. -add_time({_,_,_}=Timestamp, H, M, S) -> - add_time(calendar:now_to_datetime(Timestamp),H,M,S); +add_time({_, _, _}=Timestamp, H, M, S) -> + add_time(calendar:now_to_datetime(Timestamp), H, M, S); add_time(Datetime, H, M, S) -> apply_offset(Datetime, H, M, S). -spec add_days (datetime() | timestamp(), integer()) -> datetime(). %% @doc Add some days to the supplied `datetime()'. -add_days({_,_,_}=Timestamp, D) -> - add_days(calendar:now_to_datetime(Timestamp),D); +add_days({_, _, _}=Timestamp, D) -> + add_days(calendar:now_to_datetime(Timestamp), D); add_days(Datetime, D) -> - apply_days_offset(Datetime,D). + apply_days_offset(Datetime, D). -spec add_months (datetime() | timestamp(), integer()) -> datetime(). %% @doc Add some months to the supplied `datetime()'. -add_months({_,_,_}=Timestamp, M) -> - add_months(calendar:now_to_datetime(Timestamp),M); +add_months({_, _, _}=Timestamp, M) -> + add_months(calendar:now_to_datetime(Timestamp), M); add_months(Datetime, M) -> - apply_months_offset(Datetime,M). + apply_months_offset(Datetime, M). -spec add_years (datetime() | timestamp(), integer()) -> datetime(). %% @doc Add some years to the supplied `datetime()'. -add_years({_,_,_}=Timestamp, Y) -> - add_years(calendar:now_to_datetime(Timestamp),Y); +add_years({_, _, _}=Timestamp, Y) -> + add_years(calendar:now_to_datetime(Timestamp), Y); add_years(Datetime, Y) -> - apply_years_offset(Datetime,Y). + apply_years_offset(Datetime, Y). -spec format (datetime() | timestamp()) -> binary(). %% @doc Convert a `util:timestamp()' or a calendar-style `{date(), time()}' %% tuple to an ISO 8601 formatted string. Note that this function always %% returns a string with no offset (i.e., ending in "Z"). -format({_,_,_}=Timestamp) -> +format({_, _, _}=Timestamp) -> format(calendar:now_to_datetime(Timestamp)); -format({{Y,Mo,D}, {H,Mn,S}}) when is_float(S) -> +format({{Y, Mo, D}, {H, Mn, S}}) when is_float(S) -> FmtStr = "~4.10.0B-~2.10.0B-~2.10.0BT~2.10.0B:~2.10.0B:~9.6.0fZ", IsoStr = io_lib:format(FmtStr, [Y, Mo, D, H, Mn, S]), list_to_binary(IsoStr); -format({{Y,Mo,D}, {H,Mn,S}}) -> +format({{Y, Mo, D}, {H, Mn, S}}) -> FmtStr = "~4.10.0B-~2.10.0B-~2.10.0BT~2.10.0B:~2.10.0B:~2.10.0BZ", IsoStr = io_lib:format(FmtStr, [Y, Mo, D, H, Mn, S]), list_to_binary(IsoStr). @@ -89,7 +90,7 @@ parse(Str) -> -spec gi(string()) ->integer(). %doc get string and return integer part or 0 on error gi(DS)-> - {Int,_Rest} = string:to_integer(DS), + {Int, _Rest} = string:to_integer(DS), case Int of error->0; _->Int @@ -100,80 +101,80 @@ gi(DS)-> parse_duration(Bin) when is_binary(Bin)-> %TODO extended format parse_duration(binary_to_list(Bin)); parse_duration(Str) -> - case re:run(Str,"^(?-|\\+)?P" + case re:run(Str, "^(?-|\\+)?P" "(?:(?[0-9]+)Y)?" "(?:(?[0-9]+)M)?" "(?:(?[0-9]+)D)?" "(T(?:(?[0-9]+)H)?" "(?:(?[0-9]+)M)?" "(?:(?[0-9]+(?:\\.[0-9]+)?)S)?)?$", - [{capture,[sign,years,months,days,hours,minutes,seconds],list}]) of - {match,[Sign,Years,Months,Days,Hours,Minutes,Seconds]} -> - [{sign,Sign},{years,gi(Years)},{months,gi(Months)}, - {days,gi(Days)},{hours,gi(Hours)},{minutes,gi(Minutes)}, - {seconds,gi(Seconds)}]; + [{capture, [sign, years, months, days, hours, minutes, seconds], list}]) of + {match, [Sign, Years, Months, Days, Hours, Minutes, Seconds]} -> + [{sign, Sign}, {years, gi(Years)}, {months, gi(Months)}, + {days, gi(Days)}, {hours, gi(Hours)}, {minutes, gi(Minutes)}, + {seconds, gi(Seconds)}]; nomatch -> error(badarg) end. %% Private functions -year([Y1,Y2,Y3,Y4|Rest], Acc) -> - acc([Y1,Y2,Y3,Y4], Rest, year, Acc, fun month_or_week/2); +year([Y1, Y2, Y3, Y4 | Rest], Acc) -> + acc([Y1, Y2, Y3, Y4], Rest, year, Acc, fun month_or_week/2); year(_, _) -> error(badarg). month_or_week([], Acc) -> datetime(Acc); -month_or_week([$-,$W,W1,W2|Rest], Acc) -> - acc([W1,W2], Rest, week, Acc, fun week_day/2); -month_or_week([$-,M1,M2|Rest], Acc) -> - acc([M1,M2], Rest, month, Acc, fun month_day/2); -month_or_week([$W,W1,W2|Rest], Acc) -> - acc([W1,W2], Rest, week, Acc, fun week_day_no_hyphen/2); -month_or_week([M1,M2|Rest], Acc) -> - acc([M1,M2], Rest, month, Acc, fun month_day_no_hyphen/2); +month_or_week([$-, $W, W1, W2 | Rest], Acc) -> + acc([W1, W2], Rest, week, Acc, fun week_day/2); +month_or_week([$-, M1, M2 | Rest], Acc) -> + acc([M1, M2], Rest, month, Acc, fun month_day/2); +month_or_week([$W, W1, W2 | Rest], Acc) -> + acc([W1, W2], Rest, week, Acc, fun week_day_no_hyphen/2); +month_or_week([M1, M2 | Rest], Acc) -> + acc([M1, M2], Rest, month, Acc, fun month_day_no_hyphen/2); month_or_week(_, _) -> error(badarg). week_day([], Acc) -> datetime(Acc); -week_day([$-,D|Rest], Acc) -> +week_day([$-, D|Rest], Acc) -> acc([D], Rest, week_day, Acc, fun hour/2); week_day(_, _) -> error(badarg). week_day_no_hyphen([], Acc) -> datetime(Acc); -week_day_no_hyphen([D|Rest], Acc) -> +week_day_no_hyphen([D | Rest], Acc) -> acc([D], Rest, week_day, Acc, fun hour/2); week_day_no_hyphen(_, _) -> error(badarg). month_day([], Acc) -> datetime(Acc); -month_day([$-,D1,D2|Rest], Acc) -> - acc([D1,D2], Rest, month_day, Acc, fun hour/2); +month_day([$-, D1, D2 | Rest], Acc) -> + acc([D1, D2], Rest, month_day, Acc, fun hour/2); month_day(_, _) -> error(badarg). month_day_no_hyphen([], _) -> error(badarg); % omission of day disallowed by spec in this case -month_day_no_hyphen([D1,D2|Rest], Acc) -> - acc([D1,D2], Rest, month_day, Acc, fun hour/2); +month_day_no_hyphen([D1, D2 | Rest], Acc) -> + acc([D1, D2], Rest, month_day, Acc, fun hour/2); month_day_no_hyphen(_, _) -> error(badarg). hour([], Acc) -> datetime(Acc); -hour([$T,H1,H2,$.|Rest], Acc) -> - check_hour( list_to_integer([H1,H2]) - , acc([H1,H2], Rest, hour, Acc, fun hour_decimal/2) ); -hour([$T,H1,H2,$,|Rest], Acc) -> - check_hour( list_to_integer([H1,H2]) - , acc([H1,H2], Rest, hour, Acc, fun hour_decimal/2)); -hour([$T,H1,H2|Rest], Acc) -> - check_hour( list_to_integer([H1,H2]) - , acc([H1,H2], Rest, hour, Acc, fun minute/2)); +hour([$T, H1, H2, $. | Rest], Acc) -> + check_hour( list_to_integer([H1, H2]) + , acc([H1, H2], Rest, hour, Acc, fun hour_decimal/2)); +hour([$T, H1, H2, $, | Rest], Acc) -> + check_hour( list_to_integer([H1, H2]) + , acc([H1, H2], Rest, hour, Acc, fun hour_decimal/2)); +hour([$T, H1, H2 | Rest], Acc) -> + check_hour( list_to_integer([H1, H2]) + , acc([H1, H2], Rest, hour, Acc, fun minute/2)); hour(_, _) -> error(badarg). @@ -187,18 +188,18 @@ hour_decimal(Str, Acc) -> minute([], Acc) -> datetime(Acc); -minute([$:,M1,M2,$.|Rest], Acc) -> - acc([M1,M2], Rest, minute, Acc, fun minute_decimal/2); -minute([$:,M1,M2,$,|Rest], Acc) -> - acc([M1,M2], Rest, minute, Acc, fun minute_decimal/2); -minute([$:,M1,M2|Rest], Acc) -> - acc([M1,M2], Rest, minute, Acc, fun second/2); -minute([M1,M2,$.|Rest], Acc) -> - acc([M1,M2], Rest, minute, Acc, fun minute_decimal/2); -minute([M1,M2,$,|Rest], Acc) -> - acc([M1,M2], Rest, minute, Acc, fun minute_decimal/2); -minute([M1,M2|Rest], Acc) -> - acc([M1,M2], Rest, minute, Acc, fun second_no_colon/2); +minute([$:, M1, M2, $. | Rest], Acc) -> + acc([M1, M2], Rest, minute, Acc, fun minute_decimal/2); +minute([$:, M1, M2, $, | Rest], Acc) -> + acc([M1, M2], Rest, minute, Acc, fun minute_decimal/2); +minute([$:, M1, M2| Rest], Acc) -> + acc([M1, M2], Rest, minute, Acc, fun second/2); +minute([M1, M2, $. | Rest], Acc) -> + acc([M1, M2], Rest, minute, Acc, fun minute_decimal/2); +minute([M1, M2, $, | Rest], Acc) -> + acc([M1, M2], Rest, minute, Acc, fun minute_decimal/2); +minute([M1, M2 | Rest], Acc) -> + acc([M1, M2], Rest, minute, Acc, fun second_no_colon/2); minute(_, _) -> error(badarg). @@ -207,23 +208,23 @@ minute_decimal(Str, Acc) -> second([], Acc) -> datetime(Acc); -second([$:,S1,S2,$.|Rest], Acc) -> - acc([S1,S2], Rest, second, Acc, fun second_decimal/2); -second([$:,S1,S2,$,|Rest], Acc) -> - acc([S1,S2], Rest, second, Acc, fun second_decimal/2); -second([$:,S1,S2|Rest], Acc) -> - acc([S1,S2], Rest, second, Acc, fun offset_hour/2); +second([$:, S1, S2, $.| Rest], Acc) -> + acc([S1, S2], Rest, second, Acc, fun second_decimal/2); +second([$:, S1, S2, $, | Rest], Acc) -> + acc([S1, S2], Rest, second, Acc, fun second_decimal/2); +second([$:, S1, S2| Rest], Acc) -> + acc([S1, S2], Rest, second, Acc, fun offset_hour/2); second(_, _) -> error(badarg). second_no_colon([], Acc) -> datetime(Acc); -second_no_colon([S1,S2,$.|Rest], Acc) -> - acc([S1,S2], Rest, second, Acc, fun second_decimal/2); -second_no_colon([S1,S2,$,|Rest], Acc) -> - acc([S1,S2], Rest, second, Acc, fun second_decimal/2); -second_no_colon([S1,S2|Rest], Acc) -> - acc([S1,S2], Rest, second, Acc, fun offset_hour/2); +second_no_colon([S1, S2, $.| Rest], Acc) -> + acc([S1, S2], Rest, second, Acc, fun second_decimal/2); +second_no_colon([S1, S2, $, | Rest], Acc) -> + acc([S1, S2], Rest, second, Acc, fun second_decimal/2); +second_no_colon([S1, S2 | Rest], Acc) -> + acc([S1, S2], Rest, second, Acc, fun offset_hour/2); second_no_colon(_, _) -> error(badarg). @@ -239,25 +240,29 @@ decimal(Str, Acc, Key) -> false end, {Parts, Rest} = lists:splitwith(F, Str), - acc_float([$0,$.|Parts], Rest, Key, Acc, fun offset_hour/2). + acc_float([$0, $.|Parts], Rest, Key, Acc, fun offset_hour/2). offset_hour([], Acc) -> datetime(Acc); offset_hour([$Z], Acc) -> datetime(Acc); -offset_hour([$+,H1,H2|Rest], Acc) -> - acc([H1,H2], Rest, offset_hour, Acc, fun offset_minute/2); -offset_hour([$-,H1,H2|Rest], Acc) -> - acc([H1,H2], Rest, offset_hour, [{offset_sign, -1}|Acc], fun offset_minute/2); +offset_hour([$+, H1, H2|Rest], Acc) -> + acc([H1, H2], Rest, offset_hour, Acc, fun offset_minute/2); +offset_hour([$-, H1, H2|Rest], Acc) -> + acc([H1, H2], + Rest, + offset_hour, + [{offset_sign, -1} | Acc], + fun offset_minute/2); offset_hour(_, _) -> error(badarg). offset_minute([], Acc) -> datetime(Acc); -offset_minute([$:,M1,M2], Acc) -> - acc([M1,M2], [], offset_minute, Acc, fun datetime/2); -offset_minute([M1,M2], Acc) -> - acc([M1,M2], [], offset_minute, Acc, fun datetime/2); +offset_minute([$:, M1, M2], Acc) -> + acc([M1, M2], [], offset_minute, Acc, fun datetime/2); +offset_minute([M1, M2], Acc) -> + acc([M1, M2], [], offset_minute, Acc, fun datetime/2); offset_minute(_, _) -> error(badarg). @@ -319,7 +324,7 @@ make_date(Year, _, Week, Plist) -> %% @doc Calculate the `calendar:date()' at ISO week 1, day 1 in the supplied %% year. date_at_w01_1(Year) -> - case calendar:day_of_the_week({Year,1,1}) of + case calendar:day_of_the_week({Year, 1, 1}) of 1 -> {Year, 1, 1}; 2 -> {Year-1, 12, 31}; 3 -> {Year-1, 12, 30}; @@ -343,7 +348,7 @@ apply_offset(Datetime, H, M, S) -> apply_months_offset(Datetime, 0) -> Datetime; apply_months_offset(Datetime, AM) -> - {{Y,M,D},{H,MM,S}} = Datetime, + {{Y, M, D}, {H, MM, S}} = Datetime, AY = (Y*12)+M+AM, Year = (AY div 12), Month = @@ -351,48 +356,48 @@ apply_months_offset(Datetime, AM) -> 0 -> 12; _ -> AY rem 12 end, - find_last_valid_date({{Year,Month,D},{H,MM,S}}). + find_last_valid_date({{Year, Month, D}, {H, MM, S}}). -spec apply_days_offset (datetime(), number()) -> datetime(). %% @doc Add the specified days to `Datetime'. apply_days_offset(Datetime, AD) -> - {{Y,M,D},{H,MM,S}} = Datetime, - DaysTotal=calendar:date_to_gregorian_days({Y,M,D})+AD, - {calendar:gregorian_days_to_date(DaysTotal),{H,MM,S}}. + {{Y, M, D}, {H, MM, S}} = Datetime, + DaysTotal=calendar:date_to_gregorian_days({Y, M, D})+AD, + {calendar:gregorian_days_to_date(DaysTotal), {H, MM, S}}. -spec apply_years_offset (datetime(), number()) -> datetime(). %% @doc Add the specified years to `Datetime'. apply_years_offset(Datetime, AY) -> - {{Y,M,D},{H,MM,S}}=Datetime, - {{Y+AY,M,D},{H,MM,S}}. + {{Y, M, D}, {H, MM, S}}=Datetime, + {{Y+AY, M, D}, {H, MM, S}}. -spec find_last_valid_date(datetime()) -> datetime(). %% @doc Decrease days until found valid date'. find_last_valid_date(Datetime)-> - {{Y,M,D},{H,MM,S}} = Datetime, - case calendar:valid_date({Y,M,D}) of + {{Y, M, D}, {H, MM, S}} = Datetime, + case calendar:valid_date({Y, M, D}) of true ->Datetime; - false ->find_last_valid_date({{Y,M,D-1},{H,MM,S}}) + false ->find_last_valid_date({{Y, M, D-1}, {H, MM, S}}) end. --spec apply_duration(datetime(),string()) -> datetime(). +-spec apply_duration(datetime(), string()) -> datetime(). %% @doc Return new datetime after apply duration. -apply_duration(Datetime,Duration) -> - [{sign,_S},{years,Y},{months,M},{days,D},{hours,H}, - {minutes,MM},{seconds,SS}] = parse_duration(Duration), - D1=apply_years_offset(Datetime,Y), - D2=apply_months_offset(D1,M), - D3=apply_days_offset(D2,D), +apply_duration(Datetime, Duration) -> + [{sign, _S}, {years, Y}, {months, M}, {days, D}, {hours, H}, + {minutes, MM}, {seconds, SS}] = parse_duration(Duration), + D1=apply_years_offset(Datetime, Y), + D2=apply_months_offset(D1, M), + D3=apply_days_offset(D2, D), apply_offset(D3, H, MM, SS). --spec apply_durations(datetime(),string(),list(),integer()) -> list(). +-spec apply_durations(datetime(), string(), list(), integer()) -> list(). %% @doc Return new list with datetime tuples. -apply_durations(_Datetime,_Duration,DatetimeList,0)-> +apply_durations(_Datetime, _Duration, DatetimeList, 0)-> DatetimeList; -apply_durations(Datetime,Duration,DatetimeList,Count)-> - NewDate=apply_duration(Datetime,Duration), +apply_durations(Datetime, Duration, DatetimeList, Count)-> + NewDate=apply_duration(Datetime, Duration), NewList=lists:append(DatetimeList, [NewDate]), - apply_durations(NewDate,Duration,NewList,Count-1). + apply_durations(NewDate, Duration, NewList, Count-1). -spec is_datetime(string()) -> atom(). %% @doc Return true atom if datetime is valid. @@ -422,43 +427,51 @@ parse_interval(Bin) when is_binary(Bin) -> parse_interval(binary_to_list(Bin)); parse_interval(TimeInterval)->%"R2/P1Y3M22DT3H/2014-01-01T16:46:45Z" Tokens = string:tokens(TimeInterval, "/"), - [R,S,E]=case string:substr(TimeInterval,1,1) of + [R, S, E]=case string:substr(TimeInterval, 1, 1) of "R"-> [RS|StartEnd] = Tokens, [Start|Endd] = StartEnd, - Repeat=list_to_integer(string:substr(RS,2)), + Repeat=list_to_integer(string:substr(RS, 2)), End=binary_to_list(list_to_binary(Endd)), if - End==[]->[Repeat,binary_to_list(format(now())),Start]; - true->[Repeat,Start,End] + End==[]->[Repeat, binary_to_list(format(now())), Start]; + true->[Repeat, Start, End] end; "P"->[End|Startt] = Tokens, Start=binary_to_list(list_to_binary(Startt)), if - Start==[]->[1,binary_to_list(format(now())),End]; - true->[1,Start,End] + Start==[]->[1, binary_to_list(format(now())), End]; + true->[1, Start, End] end; _->[Start|Endd] = Tokens, End=binary_to_list(list_to_binary(Endd)), if - End==[]->[1,binary_to_list(format(now())),Start]; - true->[1,Start,End] + End==[]->[1, binary_to_list(format(now())), Start]; + true->[1, Start, End] end end, - [R,Datetime,Duration]=case is_datetime(S) of - true-> case is_datetime(E) of - true->"Can't handle this yet (Date,Date)"; - false-> case is_duration(E) of - true->[R,S,E]; - false-> error(badarg) - end - end; - false-> case is_duration(S) of - true-> case is_datetime(E) of - true-> [R,E,S];%"Duration Date"; - false-> error(badarg) - end; - false-> error(badarg) - end + [R, Datetime, Duration] = + case is_datetime(S) of + true-> is_datetime_duration(R, E, S); + false-> is_duration_datetime(R, E, S) end, - apply_durations(parse(Datetime),Duration,[],R). + apply_durations(parse(Datetime), Duration, [], R). + + +is_datetime_duration(R, E, S) -> + case is_datetime(E) of + true->"Can't handle this yet (Date, Date)"; + false-> case is_duration(E) of + true->[R, S, E]; + false-> error(badarg) + end + end. + +is_duration_datetime(R, E, S) -> + case is_duration(S) of + true-> case is_datetime(E) of + true-> [R, E, S]; %"Duration Date"; + false-> error(badarg) + end; + false-> error(badarg) + end. \ No newline at end of file diff --git a/test/iso8601_tests.erl b/test/iso8601_tests.erl index 01d91ee..8f1ec71 100644 --- a/test/iso8601_tests.erl +++ b/test/iso8601_tests.erl @@ -3,7 +3,7 @@ -include_lib("eunit/include/eunit.hrl"). --define(MN, {0,0,0}). % midnight, as a calendar:time() +-define(MN, {0, 0, 0}). % midnight, as a calendar:time() parse_fail_test_() -> F = fun iso8601:parse/1, @@ -13,95 +13,95 @@ parse_fail_test_() -> parse_year_test_() -> F = fun iso8601:parse/1, [{"parses YYYY", - ?_assertMatch({{2012,1,1}, ?MN}, F("2012"))}]. + ?_assertMatch({{2012, 1, 1}, ?MN}, F("2012"))}]. parse_month_test_() -> F = fun iso8601:parse/1, [{"parses YYYY-MM", - ?_assertMatch({{2012,12,1}, ?MN}, F("2012-12"))}]. + ?_assertMatch({{2012, 12, 1}, ?MN}, F("2012-12"))}]. parse_month_day_test_() -> F = fun iso8601:parse/1, [{"parses YYYYMMDD", - ?_assertMatch({{2012,12,12}, ?MN}, F("2012-12-12"))}, + ?_assertMatch({{2012, 12, 12}, ?MN}, F("2012-12-12"))}, {"parses YYYY-MM-DD", - ?_assertMatch({{2012,12,12}, ?MN}, F("20121212"))}]. + ?_assertMatch({{2012, 12, 12}, ?MN}, F("20121212"))}]. parse_week_test_() -> F = fun iso8601:parse/1, [{"parses 2009W01 as 2008-12-29", - ?_assertMatch({{2008,12,29}, ?MN}, F("2009W01"))}, + ?_assertMatch({{2008, 12, 29}, ?MN}, F("2009W01"))}, {"parses 2009-W01 as 2008-12-29", - ?_assertMatch({{2008,12,29}, ?MN}, F("2009-W01"))}, + ?_assertMatch({{2008, 12, 29}, ?MN}, F("2009-W01"))}, {"parses 2009W53 as 2010-01-03", - ?_assertMatch({{2009,12,28}, ?MN}, F("2009W53"))}, + ?_assertMatch({{2009, 12, 28}, ?MN}, F("2009W53"))}, {"parses 2009-W53 as 2010-01-03", - ?_assertMatch({{2009,12,28}, ?MN}, F("2009-W53"))}]. + ?_assertMatch({{2009, 12, 28}, ?MN}, F("2009-W53"))}]. parse_week_day_test_() -> F = fun iso8601:parse/1, [{"parses 2009W011 as 2008-12-29", - ?_assertMatch({{2008,12,29}, ?MN}, F("2009W011"))}, + ?_assertMatch({{2008, 12, 29}, ?MN}, F("2009W011"))}, {"parses 2009-W01-1 as 2008-12-29", - ?_assertMatch({{2008,12,29}, ?MN}, F("2009-W01-1"))}, + ?_assertMatch({{2008, 12, 29}, ?MN}, F("2009-W01-1"))}, {"parses 2009W537 as 2010-01-03", - ?_assertMatch({{2010,1,3}, ?MN}, F("2009W537"))}, + ?_assertMatch({{2010, 1, 3}, ?MN}, F("2009W537"))}, {"parses 2009-W53-7 as 2010-01-03", - ?_assertMatch({{2010,1,3}, ?MN}, F("2009-W53-7"))}]. + ?_assertMatch({{2010, 1, 3}, ?MN}, F("2009-W53-7"))}]. parse_hour_test_() -> F = fun iso8601:parse/1, [{"parses YYYYMMDDTHH", - ?_assertMatch({{2012,2,3},{4,0,0}}, F("20120203T04"))}, + ?_assertMatch({{2012, 2, 3}, {4, 0, 0}}, F("20120203T04"))}, {"parses YYYY-MM-DDTHH", - ?_assertMatch({{2012,2,3},{4,0,0}}, F("2012-02-03T04"))}]. + ?_assertMatch({{2012, 2, 3}, {4, 0, 0}}, F("2012-02-03T04"))}]. parse_fractional_hour_test_() -> F = fun iso8601:parse/1, [{"parses YYYYMMDDTHH.hh", - ?_assertMatch({{2012,2,3},{4,15,0}}, F("20120203T04.25"))}, + ?_assertMatch({{2012, 2, 3}, {4, 15, 0}}, F("20120203T04.25"))}, {"parses YYYY-MM-DDTHH.hh", - ?_assertMatch({{2012,2,3},{4,15,0}}, F("2012-02-03T04.25"))}, + ?_assertMatch({{2012, 2, 3}, {4, 15, 0}}, F("2012-02-03T04.25"))}, {"parses YYYYMMDDTHH,hh", - ?_assertMatch({{2012,2,3},{4,15,0}}, F("20120203T04,25"))}, + ?_assertMatch({{2012, 2, 3}, {4, 15, 0}}, F("20120203T04,25"))}, {"parses YYYY-MM-DDTHH,hh", - ?_assertMatch({{2012,2,3},{4,15,0}}, F("2012-02-03T04,25"))}]. + ?_assertMatch({{2012, 2, 3}, {4, 15, 0}}, F("2012-02-03T04,25"))}]. parse_minute_test_() -> F = fun iso8601:parse/1, [{"parses YYYYMMDDTHHMM", - ?_assertMatch({{2012,2,3},{4,5,0}}, F("20120203T0405"))}, + ?_assertMatch({{2012, 2, 3}, {4, 5, 0}}, F("20120203T0405"))}, {"parses YYYY-MM-DDTHH:MM", - ?_assertMatch({{2012,2,3},{4,5,0}}, F("2012-02-03T04:05"))}]. + ?_assertMatch({{2012, 2, 3}, {4, 5, 0}}, F("2012-02-03T04:05"))}]. parse_fractional_minute_test_() -> F = fun iso8601:parse/1, [{"parses YYYYMMDDTHHMM.mm", - ?_assertMatch({{2012,2,3},{4,5,15}}, F("20120203T0405.25"))}, + ?_assertMatch({{2012, 2, 3}, {4, 5, 15}}, F("20120203T0405.25"))}, {"parses YYYY-MM-DDTHHMM.mm", - ?_assertMatch({{2012,2,3},{4,5,15}}, F("2012-02-03T0405.25"))}, + ?_assertMatch({{2012, 2, 3}, {4, 5, 15}}, F("2012-02-03T0405.25"))}, {"parses YYYYMMDDTHHMM,mm", - ?_assertMatch({{2012,2,3},{4,5,15}}, F("20120203T0405,25"))}, + ?_assertMatch({{2012, 2, 3}, {4, 5, 15}}, F("20120203T0405,25"))}, {"parses YYYY-MM-DDTHHMM,mm", - ?_assertMatch({{2012,2,3},{4,5,15}}, F("2012-02-03T0405,25"))}]. + ?_assertMatch({{2012, 2, 3}, {4, 5, 15}}, F("2012-02-03T0405,25"))}]. parse_second_test_() -> F = fun iso8601:parse/1, [{"parses YYYYMMDDTHHMMSS", - ?_assertMatch({{2012,2,3},{4,5,6}}, F("20120203T040506"))}, + ?_assertMatch({{2012, 2, 3}, {4, 5, 6}}, F("20120203T040506"))}, {"parses YYYY-MM-DDTHH:MM:SS", - ?_assertMatch({{2012,2,3},{4,5,6}}, F("2012-02-03T04:05:06"))}]. + ?_assertMatch({{2012, 2, 3}, {4, 5, 6}}, F("2012-02-03T04:05:06"))}]. parse_fractional_second_test_() -> F = fun iso8601:parse/1, [{"parses YYYYMMDDTHHMMSS.ss", - ?_assertMatch({{2012,2,3},{4,5,7}}, F("20120203T040506.50"))}, + ?_assertMatch({{2012, 2, 3}, {4, 5, 7}}, F("20120203T040506.50"))}, {"parses YYYY-MM-DDTHHMMSS.ss", - ?_assertMatch({{2012,2,3},{4,5,7}}, F("2012-02-03T040506.50"))}, + ?_assertMatch({{2012, 2, 3}, {4, 5, 7}}, F("2012-02-03T040506.50"))}, {"parses YYYYMMDDTHHMMSS,ss", - ?_assertMatch({{2012,2,3},{4,5,7}}, F("20120203T040506,50"))}, + ?_assertMatch({{2012, 2, 3}, {4, 5, 7}}, F("20120203T040506,50"))}, {"parses YYYY-MM-DDTHHMMSS,ss", - ?_assertMatch({{2012,2,3},{4,5,7}}, F("2012-02-03T040506,50"))}]. + ?_assertMatch({{2012, 2, 3}, {4, 5, 7}}, F("2012-02-03T040506,50"))}]. parse_fractional_fail_test_() -> F = fun iso8601:parse/1, @@ -111,29 +111,30 @@ parse_fractional_fail_test_() -> parse_offset_test_() -> F = fun iso8601:parse/1, [{"parses YYYYMMDDTHHMMSS.ssZ", - ?_assertMatch({{2012,2,3},{4,5,7}}, F("20120203T040506.50Z"))}, + ?_assertMatch({{2012, 2, 3}, {4, 5, 7}}, F("20120203T040506.50Z"))}, {"parses YYYYMMDDTHHMMSS.ss+0400", - ?_assertMatch({{2012,2,3},{15,9,7}}, F("20120203T200506.50+0456"))}, + ?_assertMatch({{2012, 2, 3}, {15, 9, 7}}, F("20120203T200506.50+0456"))}, {"parses YYYYMMDDTHHMMSS.ss+0400", - ?_assertMatch({{2012,2,3},{17,11,7}}, F("20120203T040506.50-1306"))}]. + ?_assertMatch({{2012, 2, 3}, {17, 11, 7}}, + F("20120203T040506.50-1306"))}]. parse_duration_test_() -> F = fun iso8601:parse_duration/1, [{"parses with pos sign", - ?_assertMatch([{sign,"+"},{years,6},{months,3},{days,1}, - {hours,1},{minutes,1},{seconds,1}], + ?_assertMatch([{sign, "+"}, {years, 6}, {months, 3}, {days, 1}, + {hours, 1}, {minutes, 1}, {seconds, 1}], F("+P6Y3M1DT1H1M1.1S"))}, {"parses without sign", - ?_assertMatch([{sign,[]},{years,6},{months,3},{days,1}, - {hours,1},{minutes,1},{seconds,1}], + ?_assertMatch([{sign, []}, {years, 6}, {months, 3}, {days, 1}, + {hours, 1}, {minutes, 1}, {seconds, 1}], F("P6Y3M1DT1H1M1.1S"))}, {"parses only years", - ?_assertMatch([{sign,[]},{years,6},{months,0},{days,0}, - {hours,0},{minutes,0},{seconds,0}], + ?_assertMatch([{sign, []}, {years, 6}, {months, 0}, {days, 0}, + {hours, 0}, {minutes, 0}, {seconds, 0}], F("P6Y"))}, {"parses only minutes", - ?_assertMatch([{sign,[]},{years,0},{months,0},{days,0}, - {hours,0},{minutes,6},{seconds,0}], + ?_assertMatch([{sign, []}, {years, 0}, {months, 0}, {days, 0}, + {hours, 0}, {minutes, 6}, {seconds, 0}], F("PT6M"))}]. parse_duration_fail_test_() -> @@ -144,18 +145,18 @@ parse_duration_fail_test_() -> parse_interval_test_() -> F = fun iso8601:parse_interval/1, [{"parses date duration with repeat", - ?_assertMatch([{{2009,5,11},{15,30,0}}, - {{2010,7,21},{18,0,0}}, - {{2011,10,1},{20,30,0}}, - {{2013,12,11},{23,0,0}}, - {{2015,2,22},{1,30,0}}], + ?_assertMatch([{{2009, 5, 11}, {15, 30, 0}}, + {{2010, 7, 21}, {18, 0, 0}}, + {{2011, 10, 1}, {20, 30, 0}}, + {{2013, 12, 11}, {23, 0, 0}}, + {{2015, 2, 22}, {1, 30, 0}}], F("R5/2008-03-01T13:00:00Z/P1Y2M10DT2H30M"))}, {"parses duration date with repeat", - ?_assertMatch([{{2009,5,11},{15,30,0}}, - {{2010,7,21},{18,0,0}}, - {{2011,10,1},{20,30,0}}, - {{2013,12,11},{23,0,0}}, - {{2015,2,22},{1,30,0}}], + ?_assertMatch([{{2009, 5, 11}, {15, 30, 0}}, + {{2010, 7, 21}, {18, 0, 0}}, + {{2011, 10, 1}, {20, 30, 0}}, + {{2013, 12, 11}, {23, 0, 0}}, + {{2015, 2, 22}, {1, 30, 0}}], F("R5/P1Y2M10DT2H30M/2008-03-01T13:00:00Z"))} ]. -%TODO test Repeat/duration +%TODO test Repeat/duration \ No newline at end of file From 41fd5c678a48e027731a45201dae8f86d389f8fc Mon Sep 17 00:00:00 2001 From: "Jason L. Shiffer" Date: Sun, 4 Sep 2016 05:51:34 -0400 Subject: [PATCH 3/3] Prep release 1.2.0 --- README.md | 2 +- src/iso8601.app.src | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8a874ce..1415c99 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ as [tsloughter](https://www.github.com/tsloughter) decimal seconds patch Add it to your `rebar.config` deps: ```erlang -{'iso8601', ".*", {git, "git@github.com:kivra/erlang_iso8601.git", {tag, "1.1.2"}}} +{'iso8601', ".*", {git, "git@github.com:kivra/erlang_iso8601.git", {tag, "1.2.0"}}} ``` Format a timestamp or calendar datetime tuple: diff --git a/src/iso8601.app.src b/src/iso8601.app.src index f0d72a1..aaacb29 100644 --- a/src/iso8601.app.src +++ b/src/iso8601.app.src @@ -1,7 +1,7 @@ {application, iso8601, [ {description, "ISO 8601 date parser and formatter."}, - {vsn, "1.1.2"}, + {vsn, "1.2.0"}, {registered, []}, {applications, [kernel, stdlib]}, {env, []},