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
|
unixtime/0
|
||||||
]).
|
]).
|
||||||
|
|
||||||
|
-export([
|
||||||
|
compare/2,
|
||||||
|
compare/3
|
||||||
|
]).
|
||||||
|
|
||||||
-export([
|
-export([
|
||||||
register_parser/2,
|
register_parser/2,
|
||||||
register_parser/1,
|
register_parser/1,
|
||||||
|
@ -69,6 +74,7 @@ start() ->
|
||||||
stop() ->
|
stop() ->
|
||||||
application:stop(qdate).
|
application:stop(qdate).
|
||||||
|
|
||||||
|
|
||||||
to_string(Format) ->
|
to_string(Format) ->
|
||||||
to_string(Format, os:timestamp()).
|
to_string(Format, os:timestamp()).
|
||||||
|
|
||||||
|
@ -143,14 +149,6 @@ leading_zero(I) when I < 10 ->
|
||||||
leading_zero(I) ->
|
leading_zero(I) ->
|
||||||
integer_to_list(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) ->
|
format(Format) ->
|
||||||
to_string(Format).
|
to_string(Format).
|
||||||
|
@ -193,6 +191,93 @@ to_date(ToTZ, RawDate) ->
|
||||||
end
|
end
|
||||||
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) ->
|
extract_timezone(Unixtime) when is_integer(Unixtime) ->
|
||||||
{Unixtime, "GMT"};
|
{Unixtime, "GMT"};
|
||||||
|
@ -248,29 +333,6 @@ determine_timezone() ->
|
||||||
TZ -> TZ
|
TZ -> TZ
|
||||||
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.
|
|
||||||
|
|
||||||
%% If FromTZ is an integer, then it's an integer that represents the number of minutes
|
%% 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
|
%% relative to GMT. So we convert the date to GMT based on that number, then we can
|
||||||
%% do the other timezone conversion.
|
%% do the other timezone conversion.
|
||||||
|
@ -281,6 +343,51 @@ date_tz_to_tz(Date, FromTZ, ToTZ) ->
|
||||||
ActualToTZ = ensure_timezone(ToTZ),
|
ActualToTZ = ensure_timezone(ToTZ),
|
||||||
localtime:local_to_local(Date,FromTZ,ActualToTZ).
|
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) ->
|
try_registered_parsers(RawDate) ->
|
||||||
Parsers = qdate_srv:get_parsers(),
|
Parsers = qdate_srv:get_parsers(),
|
||||||
try_parsers(RawDate,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}]})
|
throw({error_in_parser,[{error,{Error,Reason}},{parser_key,ParserKey}]})
|
||||||
end.
|
end.
|
||||||
|
|
||||||
set_timezone(TZ) ->
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
qdate_srv:set_timezone(TZ).
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Register Formats %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
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_format(Key, Format) ->
|
register_format(Key, Format) ->
|
||||||
qdate_srv:register_format(Key, Format).
|
qdate_srv:register_format(Key, Format).
|
||||||
|
@ -371,6 +420,7 @@ deregister_format(Key) ->
|
||||||
qdate_srv:deregister_format(Key).
|
qdate_srv:deregister_format(Key).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
unixtime_to_now(T) when is_integer(T) ->
|
unixtime_to_now(T) when is_integer(T) ->
|
||||||
MegaSec = floor(T/1000000),
|
MegaSec = floor(T/1000000),
|
||||||
Secs = T - MegaSec*1000000,
|
Secs = T - MegaSec*1000000,
|
||||||
|
@ -389,8 +439,10 @@ floor(N) when N < 0 ->
|
||||||
true -> Int-1
|
true -> Int-1
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% TESTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
%% TESTS
|
|
||||||
-include_lib("eunit/include/eunit.hrl").
|
-include_lib("eunit/include/eunit.hrl").
|
||||||
|
|
||||||
%% emulates as if a forum-type website has a Site tz, and a user-specified tz
|
%% emulates as if a forum-type website has a Site tz, and a user-specified tz
|
||||||
|
@ -408,6 +460,7 @@ tz_test_() ->
|
||||||
fun(SetupData) ->
|
fun(SetupData) ->
|
||||||
{inorder,[
|
{inorder,[
|
||||||
simple_test(SetupData),
|
simple_test(SetupData),
|
||||||
|
compare_test(SetupData),
|
||||||
tz_tests(SetupData),
|
tz_tests(SetupData),
|
||||||
test_process_die(SetupData),
|
test_process_die(SetupData),
|
||||||
parser_format_test(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"))
|
?_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(_) ->
|
parser_format_test(_) ->
|
||||||
{inorder,[
|
{inorder,[
|
||||||
?_assertEqual({{2008,2,8},{0,0,0}},to_date("20080208")),
|
?_assertEqual({{2008,2,8},{0,0,0}},to_date("20080208")),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue