Skip to content
Browse files

Refactored wpart's date parsing and formatting.

Added some unit tests as well.
  • Loading branch information...
1 parent 068868c commit 5c667953962ebc7bb9a6b9e7b7c0858054f92b65 @goj goj committed Jan 23, 2007
View
2 lib/wpart-1.4/ebin/wpart.app
@@ -3,7 +3,7 @@
{vsn, "1.4"},
{modules, [wpart_app,wpart_db,wpart,wpartlib,wpart_gen,
wpart_master,wpart_valid,wpart_xs,wtpl,wtype,utf8,
- utf8_api,wpart_utils,validate_tool,wpart_cache, erlydtl_expander]},
+ utf8_api,wpart_time_str,wpart_utils,validate_tool,wpart_cache, erlydtl_expander]},
{applications, [kernel, stdlib, sasl, eptic]},
{env,[]},
{registered, []},
View
266 lib/wpart-1.4/src/wpart_time_str.erl
@@ -0,0 +1,266 @@
+%% The contents of this file are subject to the Erlang Web Public License,
+%% Version 1.0, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Web Public License along with this software. If not, it can be
+%% retrieved via the world wide web at http://www.erlang-consulting.com/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% The Initial Developer of the Original Code is Erlang Solutions Ltd.
+%% Portions created by Erlang Solutions Ltd. are Copyright 2010,
+%% Erlang Solutions Ltd. All Rights Reserved.
+
+%%%-------------------------------------------------------------------
+%%% @author Krzysztof Goj <krzysztof.goj@erlang-solutions.com>
+%%% @doc Utility functions for date tuple <-> string conversion
+%%% This code is meant to be wrapped by wtypes, not to be used on it's own.
+%%% @end
+%%%-------------------------------------------------------------------
+-module(wpart_time_str).
+
+% API
+-export([format/2, parse_input/2]).
+
+%%====================================================================
+%% API
+%%====================================================================
+-spec(format/2 :: (string(), {(tuple() | unused), (tuple() | unused)}) -> string()).
+format(_, X) when is_list(X) ->
+ X;
+format(Format, {Date, Time}) ->
+ format(Format, {Date, Time}, []);
+format(_, _) ->
+ "".
+
+-spec(parse_input/2 :: (string(), string()) ->
+ {error, bad_format} | [{atom(), integer()}]).
+parse_input(Format, Input) ->
+ parse_input(Format, Input, []).
+
+%%====================================================================
+%% Internal functions
+%%====================================================================
+
+format([$\\,Escaped|T], D, Acc) ->
+ format(T, D, Acc ++ [Escaped]);
+format("YYYY" ++ T, {{Year, _, _}, _} = D, Acc) ->
+ format(T, D, Acc ++ convert(Year, 4));
+format("YY" ++ T, {{Year, _, _}, _} = D, Acc) ->
+ format(T, D, Acc ++ convert(Year rem 100, 2));
+format("MM" ++ T, {{_, Month, _}, _} = D, Acc) ->
+ format(T, D, Acc ++ convert(Month, 2));
+format("SMONTH" ++ T, {{_, Month, _}, _} = D, Acc) ->
+ format(T, D, Acc ++ smonth(Month));
+format("MONTH" ++ T, {{_, Month, _}, _} = D, Acc) ->
+ format(T, D, Acc ++ month(Month));
+format("DD" ++ T, {{_, _, Day}, _} = D, Acc) ->
+ format(T, D, Acc ++ convert(Day, 2));
+format("SDAY" ++ T, {Date, _} = D, Acc) ->
+ format(T, D, Acc ++ sday(Date));
+format("DAY" ++ T, {Date, _} = D, Acc) ->
+ format(T, D, Acc ++ day(Date));
+format("HH" ++ T, {_, {Hour, _, _}} = D, Acc) ->
+ format(T, D, Acc ++ convert(Hour, 2));
+format("NN" ++ T, {_, {_, Min, _}} = D, Acc) ->
+ format(T, D, Acc ++ convert(Min, 2));
+format("SS" ++ T, {_, {_, _, Sec}} = D, Acc) ->
+ format(T, D, Acc ++ convert(Sec, 2));
+format([H|T], D, Acc) ->
+ format(T, D, Acc ++ [H]);
+format([], D, []) ->
+ Ref = {{1970, 1, 1}, {0, 0, 0}},
+ integer_to_list(calendar:datetime_to_gregorian_seconds(D) -
+ calendar:datetime_to_gregorian_seconds(Ref));
+format([], _, Acc) ->
+ Acc.
+
+convert(N, Len) ->
+ case integer_to_list(N) of
+ List when length(List) >= Len ->
+ List;
+ List ->
+ [$0||_ <- lists:seq(1, Len - length(List))] ++ List
+ end.
+
+smonth(1) -> "Jan";
+smonth(2) -> "Feb";
+smonth(3) -> "Mar";
+smonth(4) -> "Apr";
+smonth(5) -> "May";
+smonth(6) -> "June";
+smonth(7) -> "July";
+smonth(8) -> "Aug";
+smonth(9) -> "Sep";
+smonth(10) -> "Oct";
+smonth(11) -> "Nov";
+smonth(12) -> "Dec".
+
+month(1) -> "January";
+month(2) -> "February";
+month(3) -> "March";
+month(4) -> "April";
+month(5) -> "May";
+month(6) -> "June";
+month(7) -> "July";
+month(8) -> "August";
+month(9) -> "September";
+month(10) -> "October";
+month(11) -> "November";
+month(12) -> "December".
+
+sday(1) -> "Mon";
+sday(2) -> "Tue";
+sday(3) -> "Wed";
+sday(4) -> "Thu";
+sday(5) -> "Fri";
+sday(6) -> "Sat";
+sday(7) -> "Sun";
+sday(D) -> sday(calendar:day_of_the_week(D)).
+
+day(1) -> "Monday";
+day(2) -> "Tuesday";
+day(3) -> "Wednesday";
+day(4) -> "Thursday";
+day(5) -> "Friday";
+day(6) -> "Saturday";
+day(7) -> "Sunday";
+day(D) -> day(calendar:day_of_the_week(D)).
+
+-spec(parse_input/3 :: (string(), string(), list(tuple())) ->
+ {error, bad_format} | [{atom(), integer()}]).
+parse_input("YYYY" ++ Format, [I1, I2, I3, I4 | Input], Acc) ->
+ case catch list_to_integer([I1, I2, I3, I4]) of
+ {'EXIT', _} ->
+ {error, bad_format};
+ Year ->
+ parse_input(Format, Input, [{year, Year} | Acc])
+ end;
+parse_input("YY" ++ Format, [I1, I2 | Input], Acc) ->
+ case catch list_to_integer([I1, I2]) of
+ {'EXIT', _} ->
+ {error, bad_format};
+ Year when Year >= 70 -> %% epoch year
+ parse_input(Format, Input, [{year, 2000 + Year} | Acc]);
+ Year ->
+ parse_input(Format, Input, [{year, 1900 + Year} | Acc])
+ end;
+parse_input("MM" ++ Format, [I1, I2 | Input], Acc) ->
+ case catch list_to_integer([I1, I2]) of
+ {'EXIT', _} ->
+ {error, bad_format};
+ Month ->
+ parse_input(Format, Input, [{month, Month} | Acc])
+ end;
+parse_input("DD" ++ Format, [I1, I2 | Input], Acc) ->
+ case catch list_to_integer([I1, I2]) of
+ {'EXIT', _} ->
+ {error, bad_format};
+ Day ->
+ parse_input(Format, Input, [{day, Day} | Acc])
+ end;
+parse_input("HH" ++ Format, [I1, I2 | Input], Acc) ->
+ case catch list_to_integer([I1, I2]) of
+ {'EXIT', _} ->
+ {error, bad_format};
+ Hour ->
+ parse_input(Format, Input, [{hour, Hour} | Acc])
+ end;
+parse_input("NN" ++ Format, [I1, I2 | Input], Acc) ->
+ case catch list_to_integer([I1, I2]) of
+ {'EXIT', _} ->
+ {error, bad_format};
+ Minute ->
+ parse_input(Format, Input, [{minute, Minute} | Acc])
+ end;
+parse_input("SS" ++ Format, [I1, I2 | Input], Acc) ->
+ case catch list_to_integer([I1, I2]) of
+ {'EXIT', _} ->
+ {error, bad_format};
+ Second ->
+ parse_input(Format, Input, [{second, Second} | Acc])
+ end;
+parse_input("SMONTH" ++ Format, Input, Acc) ->
+ case smonth_to_int(Input, 1) of
+ {error, bad_format} ->
+ {error, bad_format};
+ {Smonth, NewInput} ->
+ parse_input(Format, NewInput, [{month, Smonth} | Acc])
+ end;
+parse_input("MONTH" ++ Format, Input, Acc) ->
+ case month_to_int(Input, 1) of
+ {error, bad_format} ->
+ {error, bad_format};
+ {Month, NewInput} ->
+ parse_input(Format, NewInput, [{month, Month} | Acc])
+ end;
+parse_input("DAY" ++ Format, Input, Acc) ->
+ case skip_day(Input, 1) of
+ {ok, NewInput} ->
+ parse_input(Format, NewInput, Acc);
+ Else ->
+ Else
+ end;
+parse_input("SDAY" ++ Format, Input, Acc) ->
+ case skip_sday(Input, 1) of
+ {ok, NewInput} ->
+ parse_input(Format, NewInput, Acc);
+ Else ->
+ Else
+ end;
+parse_input([_ | Format], [_ | Input], Acc) ->
+ parse_input(Format, Input, Acc);
+parse_input([], [], Acc) ->
+ Acc;
+parse_input(_, _, _) ->
+ {error, bad_format}.
+
+-spec(smonth_to_int/2 :: (string(), integer()) ->
+ {error, bad_format} | {integer(), string()}).
+smonth_to_int(_, 13) ->
+ {error, bad_format};
+smonth_to_int(Input, N) ->
+ case lists:prefix(smonth(N), Input) of
+ true ->
+ {N, lists:sublist(Input, length(smonth(N))+1, length(Input))};
+ false ->
+ smonth_to_int(Input, N+1)
+ end.
+
+-spec(month_to_int/2 :: (string(), integer()) ->
+ {error, bad_format} | {integer(), string()}).
+month_to_int(_, 13) ->
+ {error, bad_format};
+month_to_int(Input, N) ->
+ case lists:prefix(month(N), Input) of
+ true ->
+ {N, lists:sublist(Input, length(month(N))+1, length(Input))};
+ false ->
+ month_to_int(Input, N+1)
+ end.
+
+-spec(skip_day/2 :: (string(), integer()) ->
+ {error, bad_format} | {ok, string()}).
+skip_day(_, 8) ->
+ {error, bad_format};
+skip_day(Input, N) ->
+ case lists:prefix(day(N), Input) of
+ true ->
+ {ok, lists:sublist(Input, length(day(N))+1, length(Input))};
+ false ->
+ skip_day(Input, N+1)
+ end.
+
+-spec(skip_sday/2 :: (string(), integer()) ->
+ {error, bad_format} | {ok, string()}).
+skip_sday(_, 8) ->
+ {error, bad_format};
+skip_sday(Input, N) ->
+ case lists:prefix(sday(N), Input) of
+ true ->
+ {ok, lists:sublist(Input, length(sday(N))+1, length(Input))};
+ false ->
+ skip_sday(Input, N+1)
+ end.
View
218 lib/wparts-1.4/src/wtype_date.erl
@@ -56,36 +56,11 @@ handle_call(Format, #xmlText{value=Val}) ->
#xmlText{value=handle_call(Format, Val)};
handle_call([$X|_], {1970,1,1}) ->
"N/A";
-handle_call([$X|Format], Date) ->
- format(Format, Date, []);
handle_call(Format, Date) ->
- format(Format, Date, []).
-
-format("YYYY" ++ T, {Year, _, _} = D, Acc) ->
- format(T, D, Acc ++ convert(Year, 4));
-format("YY" ++ T, {Year, _, _} = D, Acc) ->
- format(T, D, Acc ++ convert(Year rem 100, 2));
-format("MM" ++ T, {_, Month, _} = D, Acc) ->
- format(T, D, Acc ++ convert(Month, 2));
-format("SMONTH" ++ T, {_, Month, _} = D, Acc) ->
- format(T, D, Acc ++ smonth(Month));
-format("MONTH" ++ T, {_, Month, _} = D, Acc) ->
- format(T, D, Acc ++ month(Month));
-format("DD" ++ T, {_, _, Day} = D, Acc) ->
- format(T, D, Acc ++ convert(Day, 2));
-format("SDAY" ++ T, Date, Acc) ->
- format(T, Date, Acc ++ sday(Date));
-format("DAY" ++ T, Date, Acc) ->
- format(T, Date, Acc ++ day(Date));
-format([H|T], D, Acc) ->
- format(T, D, Acc ++ [H]);
-format([], D, []) ->
- integer_to_list(calendar:datetime_to_gregorian_seconds({D, {0, 0, 0}}));
-format([], _, Acc) ->
- Acc.
+ get_date(Format, Date).
get_date(Format, Date) when is_tuple(Date) ->
- format(Format, Date, []);
+ wpart_time_str:format(Format, {Date, unused});
get_date(_, Date) when is_list(Date) ->
Date.
@@ -108,7 +83,7 @@ validate({Options,Input}) ->
{ok, Input};
_ ->
Format = proplists:get_value(format, Options, "YYYY-MM-DD"),
- case convert_input(Format, Input, []) of
+ case convert_input(Format, Input) of
{error, bad_format} ->
{error, {bad_date_format, Input}};
Date ->
@@ -146,181 +121,14 @@ check_max(Options, Date) ->
{error, {bad_range, Date}}
end.
-%%====================================================================
-%% Internal functions
-%%====================================================================
--spec(convert_input/3 :: (string(), string(), list(tuple())) ->
- {error, bad_format} | tuple()).
-convert_input("YYYY" ++ Format, [I1, I2, I3, I4 | Input], Acc) ->
- case catch list_to_integer([I1, I2, I3, I4]) of
- {'EXIT', _} ->
- {error, bad_format};
- Year ->
- convert_input(Format, Input, [{year, Year} | Acc])
- end;
-convert_input("YY" ++ Format, [I1, I2 | Input], Acc) ->
- case catch list_to_integer([I1, I2]) of
- {'EXIT', _} ->
- {error, bad_format};
- Year when Year >= 70 -> %% epoch year
- convert_input(Format, Input, [{year, 2000 + Year} | Acc]);
- Year ->
- convert_input(Format, Input, [{year, 1900 + Year} | Acc])
- end;
-convert_input("MM" ++ Format, [I1, I2 | Input], Acc) ->
- case catch list_to_integer([I1, I2]) of
- {'EXIT', _} ->
- {error, bad_format};
- Month ->
- convert_input(Format, Input, [{month, Month} | Acc])
- end;
-convert_input("DD" ++ Format, [I1, I2 | Input], Acc) ->
- case catch list_to_integer([I1, I2]) of
- {'EXIT', _} ->
- {error, bad_format};
- Day ->
- convert_input(Format, Input, [{day, Day} | Acc])
- end;
-convert_input("SMONTH" ++ Format, Input, Acc) ->
- case smonth_to_int(Input, 1) of
- {error, bad_format} ->
- {error, bad_format};
- {Smonth, NewInput} ->
- convert_input(Format, NewInput, [{month, Smonth} | Acc])
- end;
-convert_input("MONTH" ++ Format, Input, Acc) ->
- case month_to_int(Input, 1) of
- {error, bad_format} ->
- {error, bad_format};
- {Month, NewInput} ->
- convert_input(Format, NewInput, [{month, Month} | Acc])
- end;
-convert_input("DAY" ++ Format, Input, Acc) ->
- case skip_day(Input, 1) of
- {ok, NewInput} ->
- convert_input(Format, NewInput, Acc);
- Else ->
- Else
- end;
-convert_input("SDAY" ++ Format, Input, Acc) ->
- case skip_sday(Input, 1) of
- {ok, NewInput} ->
- convert_input(Format, NewInput, Acc);
- Else ->
- Else
- end;
-convert_input([_ | Format], [_ | Input], Acc) ->
- convert_input(Format, Input, Acc);
-convert_input([], [], Acc) ->
- {proplists:get_value(year, Acc, 0),
- proplists:get_value(month, Acc, 1),
- proplists:get_value(day, Acc, 1)};
-convert_input(_, _, _) ->
- {error, bad_format}.
-
--spec(smonth_to_int/2 :: (string(), integer()) ->
- {error, bad_format} | {integer(), string()}).
-smonth_to_int(_, 13) ->
- {error, bad_format};
-smonth_to_int(Input, N) ->
- case lists:prefix(smonth(N), Input) of
- true ->
- {N, lists:sublist(Input, length(smonth(N))+1, length(Input))};
- false ->
- smonth_to_int(Input, N+1)
+-spec(convert_input/2 :: (string(), string()) ->
+ {error, bad_format} | {integer(), integer(), integer()}).
+convert_input(Format, Input) ->
+ case wpart_time_str:parse_input(Format, Input) of
+ {error, bad_format} ->
+ {error, bad_format};
+ Values ->
+ {proplists:get_value(year, Values, 0),
+ proplists:get_value(month, Values, 0),
+ proplists:get_value(day, Values, 0)}
end.
-
--spec(month_to_int/2 :: (string(), integer()) ->
- {error, bad_format} | {integer(), string()}).
-month_to_int(_, 13) ->
- {error, bad_format};
-month_to_int(Input, N) ->
- case lists:prefix(month(N), Input) of
- true ->
- {N, lists:sublist(Input, length(month(N))+1, length(Input))};
- false ->
- month_to_int(Input, N+1)
- end.
-
--spec(skip_day/2 :: (string(), integer()) ->
- {error, bad_format} | {ok, string()}).
-skip_day(_, 8) ->
- {error, bad_format};
-skip_day(Input, N) ->
- case lists:prefix(day0(N), Input) of
- true ->
- {ok, lists:sublist(Input, length(day0(N))+1, length(Input))};
- false ->
- skip_day(Input, N+1)
- end.
-
--spec(skip_sday/2 :: (string(), integer()) ->
- {error, bad_format} | {ok, string()}).
-skip_sday(_, 8) ->
- {error, bad_format};
-skip_sday(Input, N) ->
- case lists:prefix(sday0(N), Input) of
- true ->
- {ok, lists:sublist(Input, length(sday0(N))+1, length(Input))};
- false ->
- skip_sday(Input, N+1)
- end.
-
-convert(N, Len) ->
- case integer_to_list(N) of
- List when length(List) >= Len ->
- List;
- List ->
- [$0||_ <- lists:seq(1, Len - length(List))] ++ List
- end.
-
-smonth(1) -> "Jan";
-smonth(2) -> "Feb";
-smonth(3) -> "Mar";
-smonth(4) -> "Apr";
-smonth(5) -> "May";
-smonth(6) -> "Jun";
-smonth(7) -> "Jul";
-smonth(8) -> "Aug";
-smonth(9) -> "Sep";
-smonth(10) -> "Oct";
-smonth(11) -> "Nov";
-smonth(12) -> "Dec".
-
-month(1) -> "January";
-month(2) -> "February";
-month(3) -> "March";
-month(4) -> "April";
-month(5) -> "May";
-month(6) -> "June";
-month(7) -> "July";
-month(8) -> "August";
-month(9) -> "September";
-month(10) -> "October";
-month(11) -> "November";
-month(12) -> "December".
-
--spec(sday/1 :: ({integer(), integer(), integer()}) -> string()).
-sday(Date) ->
- sday0(calendar:day_of_the_week(Date)).
-
--spec(sday0/1 :: (integer()) -> string()).
-sday0(1) -> "Mon";
-sday0(2) -> "Tue";
-sday0(3) -> "Wed";
-sday0(4) -> "Thu";
-sday0(5) -> "Fri";
-sday0(6) -> "Sat";
-sday0(7) -> "Sun".
-
--spec(day/1 :: ({integer(), integer(), integer()}) -> string()).
-day(Date) ->
- day0(calendar:day_of_the_week(Date)).
-
-day0(1) -> "Monday";
-day0(2) -> "Tuesday";
-day0(3) -> "Wednesday";
-day0(4) -> "Thursday";
-day0(5) -> "Friday";
-day0(6) -> "Saturday";
-day0(7) -> "Sunday".
View
253 lib/wparts-1.4/src/wtype_datetime.erl
@@ -30,9 +30,9 @@ handle_call(Format, #xmlText{value=Val}) ->
handle_call([$X|_], {{1970,1,1},{0,0,0}}) ->
"N/A";
handle_call([$X|Format], {Date,Time}) ->
- format(Format, {Date,Time}, []);
+ format(Format, {Date,Time});
handle_call(Format, {Date,Time}) ->
- format(Format, {Date,Time}, []).
+ format(Format, {Date,Time}).
format("Stamp", {D, T}) ->
string:join(
@@ -42,17 +42,11 @@ format("Stamp", {D, T}) ->
tuple_to_list(T)), ":")
], " ");
-format(_, X) when is_list(X) ->
- X;
-
-format(Format,{Date, Time}) ->
- format(Format, {Date, Time}, []);
-
-format(_, _) ->
- "".
+format(Format, {Date, Time}) ->
+ wpart_time_str:format(Format, {Date, Time}).
format({Date, Time}) ->
- format("YYYY-MM-DD HH:NN:SS", {Date, Time}, []).
+ format("YYYY-MM-DD HH:NN:SS", {Date, Time}).
validate({Types, undefined}) ->
case wpart_valid:is_private(Types) of
@@ -74,10 +68,10 @@ validate({Options, Input0}) ->
_ ->
Format = proplists:get_value(format, Options, "YYYY-MM-DD HH:NN:SS"),
- Input1 = case convert_input(Format, Input0, []) of
+ Input1 = case convert_input(Format, Input0) of
{error, bad_format} ->
AltFormat = proplists:get_value(alt_format, Options, "YYYY-MM-DD"),
- convert_input(AltFormat, Input0, []);
+ convert_input(AltFormat, Input0);
Inp -> Inp
end,
@@ -120,227 +114,18 @@ check_max(Options, In) ->
_ ->
{error, {bad_range, In}}
end.
-
-format("YYYY" ++ T, {{Year, _, _}, _} = D, Acc) ->
- format(T, D, Acc ++ convert(Year, 4));
-format("YY" ++ T, {{Year, _, _}, _} = D, Acc) ->
- format(T, D, Acc ++ convert(Year rem 100, 2));
-format("MM" ++ T, {{_, Month, _}, _} = D, Acc) ->
- format(T, D, Acc ++ convert(Month, 2));
-format("SMONTH" ++ T, {{_, Month, _}, _} = D, Acc) ->
- format(T, D, Acc ++ smonth(Month));
-format("MONTH" ++ T, {{_, Month, _}, _} = D, Acc) ->
- format(T, D, Acc ++ month(Month));
-format("DD" ++ T, {{_, _, Day}, _} = D, Acc) ->
- format(T, D, Acc ++ convert(Day, 2));
-format("SDAY" ++ T, {Date, _} = D, Acc) ->
- format(T, D, Acc ++ sday(Date));
-format("DAY" ++ T, {Date, _} = D, Acc) ->
- format(T, D, Acc ++ day(Date));
-format("HH" ++ T, {_, {Hour, _, _}} = D, Acc) ->
- format(T, D, Acc ++ convert(Hour, 2));
-format("NN" ++ T, {_, {_, Min, _}} = D, Acc) ->
- format(T, D, Acc ++ convert(Min, 2));
-format("SS" ++ T, {_, {_, _, Sec}} = D, Acc) ->
- format(T, D, Acc ++ convert(Sec, 2));
-format([H|T], D, Acc) ->
- format(T, D, Acc ++ [H]);
-format([], D, []) ->
- Ref = {{1970, 1, 1}, {0, 0, 0}},
- integer_to_list(calendar:datetime_to_gregorian_seconds(D) -
- calendar:datetime_to_gregorian_seconds(Ref));
-format([], _, Acc) ->
- Acc.
-
-convert(N, Len) ->
- case integer_to_list(N) of
- List when length(List) >= Len ->
- List;
- List ->
- [$0||_ <- lists:seq(1, Len - length(List))] ++ List
- end.
-
-smonth(1) -> "Jan";
-smonth(2) -> "Feb";
-smonth(3) -> "Mar";
-smonth(4) -> "Apr";
-smonth(5) -> "May";
-smonth(6) -> "June";
-smonth(7) -> "July";
-smonth(8) -> "Aug";
-smonth(9) -> "Sep";
-smonth(10) -> "Oct";
-smonth(11) -> "Nov";
-smonth(12) -> "Dec".
-
-month(1) -> "January";
-month(2) -> "February";
-month(3) -> "March";
-month(4) -> "April";
-month(5) -> "May";
-month(6) -> "June";
-month(7) -> "July";
-month(8) -> "August";
-month(9) -> "September";
-month(10) -> "October";
-month(11) -> "November";
-month(12) -> "December".
-
-sday(1) -> "Mon";
-sday(2) -> "Tue";
-sday(3) -> "Wed";
-sday(4) -> "Thu";
-sday(5) -> "Fri";
-sday(6) -> "Sat";
-sday(7) -> "Sun";
-sday(D) -> sday(calendar:day_of_the_week(D)).
-
-day(1) -> "Monday";
-day(2) -> "Tuesday";
-day(3) -> "Wednesday";
-day(4) -> "Thursday";
-day(5) -> "Friday";
-day(6) -> "Saturday";
-day(7) -> "Sunday";
-day(D) -> day(calendar:day_of_the_week(D)).
--spec(convert_input/3 :: (string(), string(), list(tuple())) ->
+-spec(convert_input/2 :: (string(), string()) ->
{error, bad_format} | {tuple(), tuple()}).
-convert_input("YYYY" ++ Format, [I1, I2, I3, I4 | Input], Acc) ->
- case catch list_to_integer([I1, I2, I3, I4]) of
- {'EXIT', _} ->
- {error, bad_format};
- Year ->
- convert_input(Format, Input, [{year, Year} | Acc])
- end;
-convert_input("YY" ++ Format, [I1, I2 | Input], Acc) ->
- case catch list_to_integer([I1, I2]) of
- {'EXIT', _} ->
- {error, bad_format};
- Year when Year >= 70 -> %% epoch year
- convert_input(Format, Input, [{year, 2000 + Year} | Acc]);
- Year ->
- convert_input(Format, Input, [{year, 1900 + Year} | Acc])
- end;
-convert_input("MM" ++ Format, [I1, I2 | Input], Acc) ->
- case catch list_to_integer([I1, I2]) of
- {'EXIT', _} ->
- {error, bad_format};
- Month ->
- convert_input(Format, Input, [{month, Month} | Acc])
- end;
-convert_input("DD" ++ Format, [I1, I2 | Input], Acc) ->
- case catch list_to_integer([I1, I2]) of
- {'EXIT', _} ->
- {error, bad_format};
- Day ->
- convert_input(Format, Input, [{day, Day} | Acc])
- end;
-convert_input("HH" ++ Format, [I1, I2 | Input], Acc) ->
- case catch list_to_integer([I1, I2]) of
- {'EXIT', _} ->
- {error, bad_format};
- Hour ->
- convert_input(Format, Input, [{hour, Hour} | Acc])
- end;
-convert_input("NN" ++ Format, [I1, I2 | Input], Acc) ->
- case catch list_to_integer([I1, I2]) of
- {'EXIT', _} ->
- {error, bad_format};
- Minute ->
- convert_input(Format, Input, [{minute, Minute} | Acc])
- end;
-convert_input("SS" ++ Format, [I1, I2 | Input], Acc) ->
- case catch list_to_integer([I1, I2]) of
- {'EXIT', _} ->
- {error, bad_format};
- Second ->
- convert_input(Format, Input, [{second, Second} | Acc])
- end;
-convert_input("SMONTH" ++ Format, Input, Acc) ->
- case smonth_to_int(Input, 1) of
- {error, bad_format} ->
- {error, bad_format};
- {Smonth, NewInput} ->
- convert_input(Format, NewInput, [{month, Smonth} | Acc])
- end;
-convert_input("MONTH" ++ Format, Input, Acc) ->
- case month_to_int(Input, 1) of
- {error, bad_format} ->
- {error, bad_format};
- {Month, NewInput} ->
- convert_input(Format, NewInput, [{month, Month} | Acc])
- end;
-convert_input("DAY" ++ Format, Input, Acc) ->
- case skip_day(Input, 1) of
- {ok, NewInput} ->
- convert_input(Format, NewInput, Acc);
- Else ->
- Else
- end;
-convert_input("SDAY" ++ Format, Input, Acc) ->
- case skip_sday(Input, 1) of
- {ok, NewInput} ->
- convert_input(Format, NewInput, Acc);
- Else ->
- Else
- end;
-convert_input([_ | Format], [_ | Input], Acc) ->
- convert_input(Format, Input, Acc);
-convert_input([], [], Acc) ->
- {{proplists:get_value(year, Acc, 0),
- proplists:get_value(month, Acc, 1),
- proplists:get_value(day, Acc, 1)},
- {proplists:get_value(hour, Acc, 0),
- proplists:get_value(minute, Acc, 0),
- proplists:get_value(second, Acc, 0)}};
-convert_input(_, _, _) ->
- {error, bad_format}.
-
--spec(smonth_to_int/2 :: (string(), integer()) ->
- {error, bad_format} | {integer(), string()}).
-smonth_to_int(_, 13) ->
- {error, bad_format};
-smonth_to_int(Input, N) ->
- case lists:prefix(smonth(N), Input) of
- true ->
- {N, lists:sublist(Input, length(smonth(N))+1, length(Input))};
- false ->
- smonth_to_int(Input, N+1)
- end.
-
--spec(month_to_int/2 :: (string(), integer()) ->
- {error, bad_format} | {integer(), string()}).
-month_to_int(_, 13) ->
- {error, bad_format};
-month_to_int(Input, N) ->
- case lists:prefix(month(N), Input) of
- true ->
- {N, lists:sublist(Input, length(month(N))+1, length(Input))};
- false ->
- month_to_int(Input, N+1)
- end.
-
--spec(skip_day/2 :: (string(), integer()) ->
- {error, bad_format} | {ok, string()}).
-skip_day(_, 8) ->
- {error, bad_format};
-skip_day(Input, N) ->
- case lists:prefix(day(N), Input) of
- true ->
- {ok, lists:sublist(Input, length(day(N))+1, length(Input))};
- false ->
- skip_day(Input, N+1)
- end.
-
--spec(skip_sday/2 :: (string(), integer()) ->
- {error, bad_format} | {ok, string()}).
-skip_sday(_, 8) ->
- {error, bad_format};
-skip_sday(Input, N) ->
- case lists:prefix(sday(N), Input) of
- true ->
- {ok, lists:sublist(Input, length(sday(N))+1, length(Input))};
- false ->
- skip_sday(Input, N+1)
+convert_input(Format, Input) ->
+ case wpart_time_str:parse_input(Format, Input) of
+ {error, bad_format} ->
+ {error, bad_format};
+ Values ->
+ {{proplists:get_value(year, Values, 0),
+ proplists:get_value(month, Values, 1),
+ proplists:get_value(day, Values, 1)},
+ {proplists:get_value(hour, Values, 0),
+ proplists:get_value(minute, Values, 0),
+ proplists:get_value(second, Values, 0)}}
end.
View
76 lib/wparts-1.4/src/wtype_time.erl
@@ -30,7 +30,7 @@
handle_call(Format, #xmlText{value = Time}) ->
#xmlText{value = handle_call(Format, Time)};
handle_call(Format, Time) ->
- format(Format, Time, []).
+ format(Format, Time).
validate({Types, undefined}) ->
case wpart_valid:is_private(Types) of
@@ -50,8 +50,8 @@ validate({Options,Input}) ->
true ->
{ok, Input};
_ ->
- Format = proplists:get_value(format, Options, "HH:MM:SS"),
- case convert_input(Format, Input, []) of
+ Format = proplists:get_value(format, Options, "HH:NN:SS"),
+ case convert_input(Format, Input) of
{error, bad_format} ->
{error, {bad_time_format, Input}};
Time ->
@@ -92,37 +92,17 @@ check_max(Options, Time) ->
%%====================================================================
%% Internal functions
%%====================================================================
--spec(convert_input/3 :: (string(), string(), list(tuple())) ->
- {error, bad_format} | {tuple(), tuple()}).
-convert_input("HH" ++ Format, [I1, I2 | Input], Acc) ->
- case catch list_to_integer([I1, I2]) of
- {'EXIT', _} ->
- {error, bad_format};
- Hour ->
- convert_input(Format, Input, [{hour, Hour} | Acc])
- end;
-convert_input("MM" ++ Format, [I1, I2 | Input], Acc) ->
- case catch list_to_integer([I1, I2]) of
- {'EXIT', _} ->
- {error, bad_format};
- Minute ->
- convert_input(Format, Input, [{minute, Minute} | Acc])
- end;
-convert_input("SS" ++ Format, [I1, I2 | Input], Acc) ->
- case catch list_to_integer([I1, I2]) of
- {'EXIT', _} ->
- {error, bad_format};
- Second ->
- convert_input(Format, Input, [{second, Second} | Acc])
- end;
-convert_input([_ | Format], [_ | Input], Acc) ->
- convert_input(Format, Input, Acc);
-convert_input([], [], Acc) ->
- {proplists:get_value(hour, Acc, 0),
- proplists:get_value(minute, Acc, 0),
- proplists:get_value(second, Acc, 0)};
-convert_input(_, _, _) ->
- {error, bad_format}.
+-spec(convert_input/2 :: (string(), string()) ->
+ {error, bad_format} | {integer(), integer(), integer()}).
+convert_input(Format, Input) ->
+ case wpart_time_str:parse_input(sanitize(Format), Input) of
+ {error, bad_format} ->
+ {error, bad_format};
+ Values ->
+ {proplists:get_value(hour, Values, 0),
+ proplists:get_value(minute, Values, 0),
+ proplists:get_value(second, Values, 0)}
+ end.
is_valid_time({H1,H2,H3}) ->
Hour = if (H1 >= 0) and (H1 < 24) -> true;
@@ -141,23 +121,15 @@ is_valid_time({H1,H2,H3}) ->
is_valid_time(_) -> false.
get_time(Format, Time) ->
- format(Format, Time, []).
+ format(Format, Time).
format(Format, Time) ->
- format(Format, Time, []).
-
-format("HH" ++ R, {Hour, _, _} = T, Acc) ->
- format(R, T, Acc ++ convert(Hour));
-format("MM" ++ R, {_, Min, _} = T, Acc) ->
- format(R, T, Acc ++ convert(Min));
-format("SS" ++ R, {_, _, Sec} = T, Acc) ->
- format(R, T, Acc ++ convert(Sec));
-format([L | R], T, Acc) ->
- format(R, T, Acc ++ [L]);
-format([], _, Acc) ->
- Acc.
-
-convert(N) when N < 10 ->
- "0" ++ integer_to_list(N);
-convert(N) ->
- integer_to_list(N).
+ wpart_time_str:format(sanitize(Format), {unused, Time}).
+
+-spec(sanitize/1 :: (string()) -> string()).
+sanitize("MM" ++ R) ->
+ "NN" ++ sanitize(R);
+sanitize([H|T]) ->
+ [H|sanitize(T)];
+sanitize([]) ->
+ [].
View
26 lib/wparts-1.4/tests/datetime_format_tests.erl
@@ -0,0 +1,26 @@
+-module(datetime_format_tests).
+
+-include_lib("eunit/include/eunit.hrl").
+
+get_time_new_syntax_test() ->
+ ?assertEqual("13:37:35", wtype_time:format("HH:NN:SS", {13, 37, 35})),
+ ?assertEqual("13:37:35", wtype_time:get_time("HH:NN:SS", {13, 37, 35})).
+
+get_time_old_syntax_test() ->
+ ?assertEqual("13:37:35", wtype_time:format("HH:MM:SS", {13, 37, 35})),
+ ?assertEqual("13:37:35", wtype_time:get_time("HH:MM:SS", {13, 37, 35})).
+
+validate_new_syntax_test() ->
+ ?assertEqual({ok, {13, 37, 35}},
+ wtype_time:validate({[{format, "HH:NN:SS"}], "13:37:35"})).
+
+validate_old_syntax_test() ->
+ ?assertEqual({ok, {13, 37, 35}},
+ wtype_time:validate({[{format, "HH:MM:SS"}], "13:37:35"})).
+
+get_date_test() ->
+ ?assertEqual("24.07.1986", wtype_date:get_date("DD.MM.YYYY", {1986, 07, 24})).
+
+validate_date_test() ->
+ ?assertEqual({ok, {1986, 07, 24}},
+ wtype_date:validate({[{format, "DD.MM.YYYY"}], "24.07.1986"})).
View
6 lib/wparts-1.4/tests/run_all.sh
@@ -0,0 +1,6 @@
+#!/bin/zsh
+cd ../../..
+./bin/compile.erl
+cd -
+erl -make
+erl -pa ../ebin/ ../../wpart-1.4/ebin/ -s datetime_format_tests test -s init stop

0 comments on commit 5c66795

Please sign in to comment.
Something went wrong with that request. Please try again.