Skip to content
Browse files

support US style date parsing using the same defaults from php as the…

… original

Signed-off-by: Jordan Wilberding <jwilberding@gmail.com>
  • Loading branch information...
1 parent 6d969cd commit 6d17415cdd3ae1e3ff74f84adbfc2f3a92842dc0 @ericbmerritt ericbmerritt committed with Jordan Wilberding Oct 17, 2011
Showing with 64 additions and 16 deletions.
  1. +64 −16 src/ec_date.erl
View
80 src/ec_date.erl
@@ -3,10 +3,17 @@
%%
%% Licensed under the MIT license
%%
-%% This module formats erlang dates in the form
-%% {{Year, Month, Day}, {Hour, Minute, Second}}
-%% to printable strings, using (almost) equivalent
-%% formatting rules as http://uk.php.net/date
+%% This module formats erlang dates in the form {{Year, Month, Day},
+%% {Hour, Minute, Second}} to printable strings, using (almost)
+%% equivalent formatting rules as http://uk.php.net/date, US vs
+%% European dates are disambiguated in the same way as
+%% http://uk.php.net/manual/en/function.strtotime.php That is, Dates
+%% in the m/d/y or d-m-y formats are disambiguated by looking at the
+%% separator between the various components: if the separator is a
+%% slash (/), then the American m/d/y is assumed; whereas if the
+%% separator is a dash (-) or a dot (.), then the European d-m-y
+%% format is assumed. To avoid potential ambiguity, it's best to use
+%% ISO 8601 (YYYY-MM-DD) dates.
%%
%% erlang has no concept of timezone so the following
%% formats are not implemented: B e I O P T Z
@@ -24,7 +31,8 @@
%% defines make sense
-define( is_num(X), (X >= $0 andalso X =< $9) ).
-define( is_meridian(X), (X==[] orelse X==[am] orelse X==[pm]) ).
--define( is_sep(X), (X==$- orelse X==$/) ).
+-define( is_us_sep(X), ( X==$/) ).
+-define( is_world_sep(X), ( X==$-) ).
-define(GREGORIAN_SECONDS_1970, 62167219200).
@@ -105,17 +113,41 @@ parse([Hour,$:,Min | PAM], {Date, _Time}, _Opts) when ?is_meridian(PAM) ->
%% Dates 23/april/1963
parse([Day,Month,Year], {_Date, Time}, _Opts) ->
{{Year, Month, Day}, Time};
-parse([Day,X,Month,X,Year], {_Date, Time}, _Opts) when ?is_sep(X) ->
+parse([Year,X,Month,X,Day], {_Date, Time}, _Opts)
+ when (?is_us_sep(X) orelse ?is_world_sep(X))
+ andalso Year > 31 ->
+ {{Year, Month, Day}, Time};
+parse([Month,X,Day,X,Year], {_Date, Time}, _Opts) when ?is_us_sep(X) ->
+ {{Year, Month, Day}, Time};
+parse([Day,X,Month,X,Year], {_Date, Time}, _Opts) when ?is_world_sep(X) ->
{{Year, Month, Day}, Time};
%% Date/Times 22 Aug 2008 6:35 PM
+parse([Year,X,Month,X,Day,Hour,$:,Min | PAM], _Date, _Opts)
+ when ?is_meridian(PAM) andalso
+ (?is_us_sep(X) orelse ?is_world_sep(X))
+ andalso Year > 31 ->
+ {{Year, Month, Day}, {hour(Hour, PAM), Min, 0}};
parse([Day,X,Month,X,Year,Hour,$:,Min | PAM], _Date, _Opts)
- when ?is_meridian(PAM) andalso ?is_sep(X) ->
+ when ?is_meridian(PAM) andalso ?is_world_sep(X) ->
{{Year, Month, Day}, {hour(Hour, PAM), Min, 0}};
+parse([Month,X,Day,X,Year,Hour,$:,Min | PAM], _Date, _Opts)
+ when ?is_meridian(PAM) andalso ?is_us_sep(X) ->
+ {{Year, Month, Day}, {hour(Hour, PAM), Min, 0}};
+
+parse([Year,X,Month,X,Day,Hour,$:,Min,$:,Sec | PAM], _Now, _Opts)
+ when ?is_meridian(PAM) andalso
+ (?is_us_sep(X) orelse ?is_world_sep(X))
+ andalso Year > 31 ->
+ {{Year, Month, Day}, {hour(Hour, PAM), Min, Sec}};
+parse([Month,X,Day,X,Year,Hour,$:,Min,$:,Sec | PAM], _Now, _Opts)
+ when ?is_meridian(PAM) andalso ?is_us_sep(X) ->
+ {{Year, Month, Day}, {hour(Hour, PAM), Min, Sec}};
parse([Day,X,Month,X,Year,Hour,$:,Min,$:,Sec | PAM], _Now, _Opts)
- when ?is_meridian(PAM) andalso ?is_sep(X) ->
+ when ?is_meridian(PAM) andalso ?is_world_sep(X) ->
{{Year, Month, Day}, {hour(Hour, PAM), Min, Sec}};
+
parse([Day,Month,Year,Hour,$:,Min | PAM], _Now, _Opts)
when ?is_meridian(PAM) ->
{{Year, Month, Day}, {hour(Hour, PAM), Min, 0}};
@@ -492,9 +524,7 @@ basic_parse_test_() ->
?_assertEqual({{2008,8,22}, {6,35,12}},
parse("22-Aug-2008 6:35:12 AM", ?DATE)),
?_assertEqual({{2008,8,22}, {6,35,0}},
- parse("22/Aug/2008 6:35 AM", ?DATE)),
- ?_assertEqual({{2008,8,22}, {6,35,0}},
- parse("22/August/2008 6:35 AM", ?DATE)),
+ parse("August/22/2008 6:35 AM", ?DATE)),
?_assertEqual({{2008,8,22}, {6,35,0}},
parse("22 August 2008 6:35 AM", ?DATE)),
?_assertEqual({{2008,8,22}, {6,35,0}},
@@ -514,11 +544,29 @@ basic_parse_test_() ->
?_assertEqual({{2001,3,10}, {3,45,39}},
parse("3:45:39", ?DATE)),
?_assertEqual({{1963,4,23}, {17,16,17}},
- parse("23/4/1963", ?DATE)),
+ parse("23-4-1963", ?DATE)),
+ ?_assertEqual({{1963,4,23}, {17,16,17}},
+ parse("23-april-1963", ?DATE)),
+ ?_assertEqual({{1963,4,23}, {17,16,17}},
+ parse("23-apr-1963", ?DATE)),
+ ?_assertEqual({{1963,4,23}, {17,16,17}},
+ parse("4/23/1963", ?DATE)),
+ ?_assertEqual({{1963,4,23}, {17,16,17}},
+ parse("april/23/1963", ?DATE)),
+ ?_assertEqual({{1963,4,23}, {17,16,17}},
+ parse("apr/23/1963", ?DATE)),
+ ?_assertEqual({{1963,4,23}, {17,16,17}},
+ parse("1963/4/23", ?DATE)),
+ ?_assertEqual({{1963,4,23}, {17,16,17}},
+ parse("1963/april/23", ?DATE)),
+ ?_assertEqual({{1963,4,23}, {17,16,17}},
+ parse("1963/apr/23", ?DATE)),
+ ?_assertEqual({{1963,4,23}, {17,16,17}},
+ parse("1963-4-23", ?DATE)),
?_assertEqual({{1963,4,23}, {17,16,17}},
- parse("23/april/1963", ?DATE)),
+ parse("1963-4-23", ?DATE)),
?_assertEqual({{1963,4,23}, {17,16,17}},
- parse("23/apr/1963", ?DATE)),
+ parse("1963-apr-23", ?DATE)),
?_assertThrow({?MODULE, {bad_date, "23/ap/195"}},
parse("23/ap/195", ?DATE)),
?_assertEqual({{2001,3,10}, {6,45,0}},
@@ -538,9 +586,9 @@ parse_with_days_test_() ->
?_assertEqual({{2008,8,22}, {6,35,12}},
parse("Sunday 22-Aug-2008 6:35:12 AM", ?DATE)),
?_assertEqual({{2008,8,22}, {6,35,0}},
- parse("Sun 22/Aug/2008 6:35 AM", ?DATE)),
+ parse("Sun 22-Aug-2008 6:35 AM", ?DATE)),
?_assertEqual({{2008,8,22}, {6,35,0}},
- parse("THURSDAY, 22/August/2008 6:35 AM", ?DATE)),
+ parse("THURSDAY, 22-August-2008 6:35 AM", ?DATE)),
?_assertEqual({{2008,8,22}, {6,35,0}},
parse("THU 22 August 2008 6:35 AM", ?DATE)),
?_assertEqual({{2008,8,22}, {6,35,0}},

0 comments on commit 6d17415

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