Browse Source

Improve floatformat.

Fixes #41, #53.
Andreas Stenius 11 years ago
parent
commit
b57284af4f
2 changed files with 69 additions and 26 deletions
  1. 21 17
      src/erlydtl_filters.erl
  2. 48 9
      tests/src/erlydtl_unittests.erl

+ 21 - 17
src/erlydtl_filters.erl

@@ -66,6 +66,7 @@
         filesizeformat/1,
         first/1,
         fix_ampersands/1,
+        floatformat/1,
         floatformat/2,
         force_escape/1,
         format_integer/1,
@@ -328,33 +329,30 @@ fix_ampersands(Input) when is_list(Input) ->
 
 %% @doc When used without an argument, rounds a floating-point number to one decimal place
 %% -- but only if there's a decimal part to be displayed
-floatformat(Number, Place) when is_binary(Number) ->
-    floatformat(binary_to_list(Number), Place);
+floatformat(Number) ->
+    floatformat(Number, []).
+
 floatformat(Number, Place) ->
-    floatformat_io(Number, cast_to_integer(Place)).
+    floatformat_io(cast_to_float(Number), cast_to_integer(Place)).
 
 floatformat_io(Number, []) ->
     floatformat_io(Number, -1);
+floatformat_io(Number, 0) ->
+    hd(io_lib:format("~B", [erlang:round(Number)]));
 floatformat_io(Number, Precision) when Precision > 0 ->
-    Format = lists:flatten(io_lib:format("~~.~Bf",[Precision])),
-    [Result] = io_lib:format(Format,[Number]),
-    Result;
+    hd(io_lib:format("~.*f",[Precision, Number]));
 floatformat_io(Number, Precision) when Precision < 0 ->   
     Round = erlang:round(Number),
     RoundPrecision = round(Number, -Precision),
-    case RoundPrecision == Round of
-        true ->
-            %Format = lists:flatten(io_lib:format("~~~BB",[-Precision])),
-            [Result] = io_lib:format("~B",[Round]);
-        false ->
-            Format = lists:flatten(io_lib:format("~~.~Bf",[-Precision])),
-            [Result] = io_lib:format(Format,[RoundPrecision])
-    end,
-    Result.
+    if RoundPrecision == Round ->
+            floatformat_io(Round, 0);
+       true ->
+            floatformat_io(RoundPrecision, -Precision)
+    end.
 
 round(Number, Precision) ->
     P = math:pow(10, Precision),
-    round(Number * P) / P.
+    erlang:round(Number * P) / P.
 
 %% @doc Applies HTML escaping to a string.
 force_escape(Input) when is_list(Input) ->
@@ -720,7 +718,13 @@ cast_to_float(Input) when is_float(Input) ->
     Input;
 cast_to_float(Input) when is_integer(Input) ->
     Input + 0.0;
-cast_to_float(Input) ->
+cast_to_float(Input) when is_binary(Input) ->
+    try binary_to_float(Input)
+    catch
+        error:_Reason ->
+            binary_to_integer(Input) + 0.0
+    end;
+cast_to_float(Input) when is_list(Input) ->
     try list_to_float(Input)
     catch
         error:_Reason ->

+ 48 - 9
tests/src/erlydtl_unittests.erl

@@ -468,15 +468,54 @@ tests() ->
 		  {"|floatformat:\"-1\"",
 		   <<"{{ var1|floatformat:\"-1\" }}">>, [{var1, 34.23234}],
 		   <<"34.2">>},
-		  %%         ?assertEqual( "", erlydtl_filters:floatformat(,)),
-		  %%         ?assertEqual( "34", erlydtl_filters:floatformat(34.00000,-1)),
-		  %%         ?assertEqual( "34.3", erlydtl_filters:floatformat(34.26000,-1)),
-		  %%         ?assertEqual( "34.232", erlydtl_filters:floatformat(34.23234,3)),
-		  %%         ?assertEqual( "34.000", erlydtl_filters:floatformat(34.00000,3)),
-		  %%         ?assertEqual( "34.260", erlydtl_filters:floatformat(34.26000,3)),
-		  %%         ?assertEqual( "34.232", erlydtl_filters:floatformat(34.23234,-3)),
-		  %%         ?assertEqual( "34", erlydtl_filters:floatformat(34.00000,-3)),
-		  %%         ?assertEqual( "34.260", erlydtl_filters:floatformat(34.26000,-3)).
+          {"int |floatformat",
+           <<"{{ var1|floatformat:\"-1\" }}">>, [{var1, 123}],
+           <<"123">>},
+          {"string |floatformat",
+           <<"{{ var1|floatformat:\"-1\" }}">>, [{var1, "123.321"}],
+           <<"123.3">>},
+          {"binary |floatformat",
+           <<"{{ var1|floatformat:\"-1\" }}">>, [{var1, <<"123.321">>}],
+           <<"123.3">>},
+
+          %% from: https://docs.djangoproject.com/en/1.6/ref/templates/builtins/#floatformat
+		  {"1.a) |floatformat",
+		   <<"{{ var1|floatformat }}">>, [{var1, 34.23234}],
+		   <<"34.2">>},
+		  {"1.b) |floatformat",
+		   <<"{{ var1|floatformat }}">>, [{var1, 34.00000}],
+		   <<"34">>},
+		  {"1.c) |floatformat",
+		   <<"{{ var1|floatformat }}">>, [{var1, 34.26000}],
+		   <<"34.3">>},
+		  {"2.a) |floatformat:\"3\"",
+		   <<"{{ var1|floatformat:\"3\" }}">>, [{var1, 34.23234}],
+		   <<"34.232">>},
+		  {"2.b) |floatformat:\"3\"",
+		   <<"{{ var1|floatformat:\"3\" }}">>, [{var1, 34.00000}],
+		   <<"34.000">>},
+		  {"2.c) |floatformat:\"3\"",
+		   <<"{{ var1|floatformat:\"3\" }}">>, [{var1, 34.26000}],
+		   <<"34.260">>},
+		  {"3.a) |floatformat:\"0\"",
+		   <<"{{ var1|floatformat:\"0\" }}">>, [{var1, 34.23234}],
+		   <<"34">>},
+		  {"3.b) |floatformat:\"0\"",
+		   <<"{{ var1|floatformat:\"0\" }}">>, [{var1, 34.00000}],
+		   <<"34">>},
+		  {"3.c) |floatformat:\"0\"",
+		   <<"{{ var1|floatformat:\"0\" }}">>, [{var1, 39.56000}],
+		   <<"40">>},
+		  {"4.a) |floatformat:\"-3\"",
+		   <<"{{ var1|floatformat:\"-3\" }}">>, [{var1, 34.23234}],
+		   <<"34.232">>},
+		  {"4.b) |floatformat:\"-3\"",
+		   <<"{{ var1|floatformat:\"-3\" }}">>, [{var1, 34.00000}],
+		   <<"34">>},
+		  {"4.c) |floatformat:\"-3\"",
+		   <<"{{ var1|floatformat:\"-3\" }}">>, [{var1, 34.26000}],
+		   <<"34.260">>},
+
 		  {"|force_escape",
 		   <<"{{ var1|force_escape }}">>, [{var1, "Ben & Jerry's <=> \"The World's Best Ice Cream\""}],
 		   <<"Ben &amp; Jerry&#039;s &lt;=&gt; &quot;The World&#039;s Best Ice Cream&quot;">>},