Add compare/2 and compare/3
This commit is contained in:
parent
97ad84deb8
commit
0770b0a5da
1 changed files with 163 additions and 93 deletions
256
src/qdate.erl
256
src/qdate.erl
|
@ -20,6 +20,11 @@
|
|||
unixtime/0
|
||||
]).
|
||||
|
||||
-export([
|
||||
compare/2,
|
||||
compare/3
|
||||
]).
|
||||
|
||||
-export([
|
||||
register_parser/2,
|
||||
register_parser/1,
|
||||
|
@ -69,6 +74,7 @@ start() ->
|
|||
stop() ->
|
||||
application:stop(qdate).
|
||||
|
||||
|
||||
to_string(Format) ->
|
||||
to_string(Format, os:timestamp()).
|
||||
|
||||
|
@ -143,14 +149,6 @@ leading_zero(I) when I < 10 ->
|
|||
leading_zero(I) ->
|
||||
integer_to_list(I).
|
||||
|
||||
get_timezone_shift(TZ, Date) ->
|
||||
case localtime:tz_shift(Date, TZ) of
|
||||
unable_to_detect -> {error,unable_to_detect};
|
||||
{error,T} -> {error,T};
|
||||
{Sh, _DstSh} -> Sh;
|
||||
Sh -> Sh
|
||||
end.
|
||||
|
||||
|
||||
format(Format) ->
|
||||
to_string(Format).
|
||||
|
@ -193,6 +191,93 @@ to_date(ToTZ, RawDate) ->
|
|||
end
|
||||
end.
|
||||
|
||||
%% This converts dates without regard to timezone.
|
||||
%% Unixtime just goes to UTC
|
||||
raw_to_date(Unixtime) when is_integer(Unixtime) ->
|
||||
unixtime_to_date(Unixtime);
|
||||
raw_to_date(DateString) when is_list(DateString) ->
|
||||
ec_date:parse(DateString, get_deterministic_datetime());
|
||||
raw_to_date(Now = {_,_,_}) ->
|
||||
calendar:now_to_datetime(Now);
|
||||
raw_to_date(Date = {{_,_,_},{_,_,_}}) ->
|
||||
Date.
|
||||
|
||||
get_deterministic_datetime() ->
|
||||
DateZero = {1970,1,1},
|
||||
TimeZero = {0,0,0},
|
||||
case application:get_env(qdate, deterministic_parsing) of
|
||||
{ok, {zero, zero}} -> {DateZero, TimeZero};
|
||||
{ok, {zero, now}} -> {DateZero, time()};
|
||||
{ok, {now, zero}} -> {date(), TimeZero};
|
||||
{ok, {now, now}} -> {date(), time()};
|
||||
undefined -> {DateZero, TimeZero};
|
||||
{ok, Val} -> throw({invalid_env_var, {qdate, deterministic_parsing, Val}})
|
||||
end.
|
||||
|
||||
|
||||
to_unixtime(Unixtime) when is_integer(Unixtime) ->
|
||||
Unixtime;
|
||||
to_unixtime({MegaSecs,Secs,_}) ->
|
||||
MegaSecs*1000000 + Secs;
|
||||
to_unixtime(ToParse) ->
|
||||
%% We want to treat all unixtimes as GMT
|
||||
Date = to_date("GMT", ToParse),
|
||||
calendar:datetime_to_gregorian_seconds(Date) - ?UNIXTIME_BASE.
|
||||
|
||||
unixtime() ->
|
||||
to_unixtime(os:timestamp()).
|
||||
|
||||
to_now(Now = {_,_,_}) ->
|
||||
Now;
|
||||
to_now(ToParse) ->
|
||||
Unixtime = to_unixtime(ToParse),
|
||||
unixtime_to_now(Unixtime).
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Comparisons %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
compare(A, B) ->
|
||||
NowA = to_now(A),
|
||||
NowB = to_now(B),
|
||||
if
|
||||
NowA == NowB -> 0;
|
||||
NowA < NowB -> -1;
|
||||
NowA > NowB -> 1
|
||||
end.
|
||||
|
||||
compare(A, Op, B) ->
|
||||
Comp = compare(A, B),
|
||||
case Op of
|
||||
'==' -> Comp =:= 0;
|
||||
'=' -> Comp =:= 0;
|
||||
|
||||
'!=' -> Comp =/= 0;
|
||||
'=/=' -> Comp =/= 0;
|
||||
'/=' -> Comp =/= 0;
|
||||
|
||||
'<' -> Comp =:= -1;
|
||||
'<=' -> Comp =:= -1 orelse Comp =:= 0;
|
||||
'=<' -> Comp =:= -1 orelse Comp =:= 0;
|
||||
|
||||
'>' -> Comp =:= 1;
|
||||
'>=' -> Comp =:= 1 orelse Comp =:= 0;
|
||||
'=>' -> Comp =:= 1 orelse Comp =:= 0
|
||||
end.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Timezone Stuff %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
get_timezone_shift(TZ, Date) ->
|
||||
case localtime:tz_shift(Date, TZ) of
|
||||
unable_to_detect -> {error,unable_to_detect};
|
||||
{error,T} -> {error,T};
|
||||
{Sh, _DstSh} -> Sh;
|
||||
Sh -> Sh
|
||||
end.
|
||||
|
||||
|
||||
extract_timezone(Unixtime) when is_integer(Unixtime) ->
|
||||
{Unixtime, "GMT"};
|
||||
|
@ -248,29 +333,6 @@ determine_timezone() ->
|
|||
TZ -> TZ
|
||||
end.
|
||||
|
||||
%% This converts dates without regard to timezone.
|
||||
%% Unixtime just goes to UTC
|
||||
raw_to_date(Unixtime) when is_integer(Unixtime) ->
|
||||
unixtime_to_date(Unixtime);
|
||||
raw_to_date(DateString) when is_list(DateString) ->
|
||||
ec_date:parse(DateString, get_deterministic_datetime());
|
||||
raw_to_date(Now = {_,_,_}) ->
|
||||
calendar:now_to_datetime(Now);
|
||||
raw_to_date(Date = {{_,_,_},{_,_,_}}) ->
|
||||
Date.
|
||||
|
||||
get_deterministic_datetime() ->
|
||||
DateZero = {1970,1,1},
|
||||
TimeZero = {0,0,0},
|
||||
case application:get_env(qdate, deterministic_parsing) of
|
||||
{ok, {zero, zero}} -> {DateZero, TimeZero};
|
||||
{ok, {zero, now}} -> {DateZero, time()};
|
||||
{ok, {now, zero}} -> {date(), TimeZero};
|
||||
{ok, {now, now}} -> {date(), time()};
|
||||
undefined -> {DateZero, TimeZero};
|
||||
{ok, Val} -> throw({invalid_env_var, {qdate, deterministic_parsing, Val}})
|
||||
end.
|
||||
|
||||
%% If FromTZ is an integer, then it's an integer that represents the number of minutes
|
||||
%% relative to GMT. So we convert the date to GMT based on that number, then we can
|
||||
%% do the other timezone conversion.
|
||||
|
@ -281,6 +343,51 @@ date_tz_to_tz(Date, FromTZ, ToTZ) ->
|
|||
ActualToTZ = ensure_timezone(ToTZ),
|
||||
localtime:local_to_local(Date,FromTZ,ActualToTZ).
|
||||
|
||||
set_timezone(TZ) ->
|
||||
qdate_srv:set_timezone(TZ).
|
||||
|
||||
set_timezone(Key,TZ) ->
|
||||
qdate_srv:set_timezone(Key, TZ).
|
||||
|
||||
get_timezone() ->
|
||||
qdate_srv:get_timezone().
|
||||
|
||||
get_timezone(Key) ->
|
||||
qdate_srv:get_timezone(Key).
|
||||
|
||||
ensure_timezone(Key) when is_atom(Key) orelse is_tuple(Key) ->
|
||||
case get_timezone(Key) of
|
||||
undefined -> throw({timezone_key_not_found,Key});
|
||||
ToTZ -> ToTZ
|
||||
end;
|
||||
ensure_timezone(TZ) when is_binary(TZ) ->
|
||||
binary_to_list(TZ);
|
||||
ensure_timezone(TZ) when is_list(TZ) ->
|
||||
TZ.
|
||||
|
||||
clear_timezone() ->
|
||||
qdate_srv:clear_timezone().
|
||||
|
||||
clear_timezone(Key) ->
|
||||
qdate_srv:clear_timezone(Key).
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Register Parsers %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
register_parser(Key, Parser) when is_function(Parser,1) ->
|
||||
qdate_srv:register_parser(Key,Parser).
|
||||
|
||||
register_parser(Parser) when is_function(Parser,1) ->
|
||||
qdate_srv:register_parser(Parser).
|
||||
|
||||
deregister_parser(Key) ->
|
||||
qdate_srv:deregister_parser(Key).
|
||||
|
||||
deregister_parsers() ->
|
||||
qdate_srv:deregister_parsers().
|
||||
|
||||
try_registered_parsers(RawDate) ->
|
||||
Parsers = qdate_srv:get_parsers(),
|
||||
try_parsers(RawDate,Parsers).
|
||||
|
@ -302,67 +409,9 @@ try_parsers(RawDate,[{ParserKey,Parser}|Parsers]) ->
|
|||
throw({error_in_parser,[{error,{Error,Reason}},{parser_key,ParserKey}]})
|
||||
end.
|
||||
|
||||
set_timezone(TZ) ->
|
||||
qdate_srv:set_timezone(TZ).
|
||||
|
||||
set_timezone(Key,TZ) ->
|
||||
qdate_srv:set_timezone(Key, TZ).
|
||||
|
||||
get_timezone() ->
|
||||
qdate_srv:get_timezone().
|
||||
|
||||
get_timezone(Key) ->
|
||||
qdate_srv:get_timezone(Key).
|
||||
|
||||
|
||||
ensure_timezone(Key) when is_atom(Key) orelse is_tuple(Key) ->
|
||||
case get_timezone(Key) of
|
||||
undefined -> throw({timezone_key_not_found,Key});
|
||||
ToTZ -> ToTZ
|
||||
end;
|
||||
ensure_timezone(TZ) when is_binary(TZ) ->
|
||||
binary_to_list(TZ);
|
||||
ensure_timezone(TZ) when is_list(TZ) ->
|
||||
TZ.
|
||||
|
||||
|
||||
clear_timezone() ->
|
||||
qdate_srv:clear_timezone().
|
||||
|
||||
clear_timezone(Key) ->
|
||||
qdate_srv:clear_timezone(Key).
|
||||
|
||||
|
||||
to_unixtime(Unixtime) when is_integer(Unixtime) ->
|
||||
Unixtime;
|
||||
to_unixtime({MegaSecs,Secs,_}) ->
|
||||
MegaSecs*1000000 + Secs;
|
||||
to_unixtime(ToParse) ->
|
||||
%% We want to treat all unixtimes as GMT
|
||||
Date = to_date("GMT", ToParse),
|
||||
calendar:datetime_to_gregorian_seconds(Date) - ?UNIXTIME_BASE.
|
||||
|
||||
unixtime() ->
|
||||
to_unixtime(os:timestamp()).
|
||||
|
||||
to_now(Now = {_,_,_}) ->
|
||||
Now;
|
||||
to_now(ToParse) ->
|
||||
Unixtime = to_unixtime(ToParse),
|
||||
unixtime_to_now(Unixtime).
|
||||
|
||||
|
||||
register_parser(Key, Parser) when is_function(Parser,1) ->
|
||||
qdate_srv:register_parser(Key,Parser).
|
||||
|
||||
register_parser(Parser) when is_function(Parser,1) ->
|
||||
qdate_srv:register_parser(Parser).
|
||||
|
||||
deregister_parser(Key) ->
|
||||
qdate_srv:deregister_parser(Key).
|
||||
|
||||
deregister_parsers() ->
|
||||
qdate_srv:deregister_parsers().
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Register Formats %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
register_format(Key, Format) ->
|
||||
qdate_srv:register_format(Key, Format).
|
||||
|
@ -371,6 +420,7 @@ deregister_format(Key) ->
|
|||
qdate_srv:deregister_format(Key).
|
||||
|
||||
|
||||
|
||||
unixtime_to_now(T) when is_integer(T) ->
|
||||
MegaSec = floor(T/1000000),
|
||||
Secs = T - MegaSec*1000000,
|
||||
|
@ -389,8 +439,10 @@ floor(N) when N < 0 ->
|
|||
true -> Int-1
|
||||
end.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% TESTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
%% TESTS
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
|
||||
%% emulates as if a forum-type website has a Site tz, and a user-specified tz
|
||||
|
@ -408,6 +460,7 @@ tz_test_() ->
|
|||
fun(SetupData) ->
|
||||
{inorder,[
|
||||
simple_test(SetupData),
|
||||
compare_test(SetupData),
|
||||
tz_tests(SetupData),
|
||||
test_process_die(SetupData),
|
||||
parser_format_test(SetupData),
|
||||
|
@ -496,6 +549,23 @@ simple_test(_) ->
|
|||
?_assertEqual({{2013,1,1},{0,15,15}},to_date("GMT", "December 31, 2012 6:15:15pm CST"))
|
||||
]}.
|
||||
|
||||
|
||||
compare_test(_) ->
|
||||
{inorder,[
|
||||
?_assertEqual(true, compare({{2013,9,10},{0,0,0}},'=',"Sep 10th, 2013 12:00am")),
|
||||
?_assertEqual(true, compare("9/10/2013 1am EST",'==',"Sep 10th, 2013 12:00:00am CST")),
|
||||
?_assertEqual(true, compare({{2013,9,10},{0,0,0}},'=<',"Sep 10th, 2013 12:00am")),
|
||||
?_assertEqual(false, compare({{2013,9,10},{0,0,1}},'=',"Sep 10th, 2013 12:00am")),
|
||||
?_assertEqual(true, compare({{2013,9,10},{0,0,1}},'=/=',"Sep 10th, 2013 12:00am")),
|
||||
?_assertEqual(true, compare({{2013,9,10},{0,0,1}},'>',"Sep 10th, 2013 12:00am")),
|
||||
?_assertEqual(false, compare({{2013,9,10},{0,0,1}},'<',"Sep 10th, 2013 12:00am")),
|
||||
?_assertEqual(true, compare({{2013,9,10},{0,0,1}},'<',"Sep 10th, 2013 12:00:02am")),
|
||||
?_assertEqual(true, compare({{2013,9,10},{0,0,1}},'<',"Sep 10th, 2013 12:02am")),
|
||||
?_assertEqual(true, compare({{2013,9,10},{0,0,1}},'<',"Sep 10th, 2013 1am")),
|
||||
?_assertEqual(true, compare({{2013,9,9},{23,59,59}},'<',"Sep 10th, 2013 12am")),
|
||||
?_assertEqual(false, compare({{2013,9,9},{23,59,59}},'>',"Sep 10th, 2013 12am"))
|
||||
]}.
|
||||
|
||||
parser_format_test(_) ->
|
||||
{inorder,[
|
||||
?_assertEqual({{2008,2,8},{0,0,0}},to_date("20080208")),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue