diff --git a/src/ezic_compile.erl b/src/ezic_compile.erl index 5775ae3..2849c8b 100644 --- a/src/ezic_compile.erl +++ b/src/ezic_compile.erl @@ -52,7 +52,7 @@ flatten(Zones, Rules) -> SortedZoneSet= lists:sort(fun zone_sorter/2, ZoneSet), flatten_set(SortedZoneSet, NeededRules), - ?debug("Sorted Zones: ~p", [SortedZoneSet]), +% ?debug("Sorted Zones: ~p", [SortedZoneSet]), flatten(RestZones, Rules). @@ -60,7 +60,7 @@ flatten(Zones, Rules) -> zone_sorter(Z1=#zone{until=U1},#zone{until=U2}) -> - ezic_record:compare_datetimes(U1, U2). + ezic_date:compare_datetimes(U1, U2). %% case (D1 =< D2) of @@ -86,14 +86,11 @@ make_rule_zone_filter(#zone{rule=Rule}) -> fun(#rule{name=Rule})-> true; (_)->false end. +% accepts a rule, and returns true if it exists between the two years given make_rule_time_filter(D1, D2) -> fun(#rule{from=F, to=T}) -> - GoodFrom= ezic_record:compare_datetimes(D1, F) =:= true - andalso ezic_record:compare_datetimes(F, D2) =:= true, - GoodTo= ezic_record:compare_datetimes(D1, T) =:= true - andalso ezic_record:compare_datetimes(T, D2) =:= true, - GoodFrom orelse GoodTo - end. + ezic_date:overlap({D1,D2}, {F,T}) + end. diff --git a/src/ezic_date.erl b/src/ezic_date.erl index 51ce110..94142a4 100644 --- a/src/ezic_date.erl +++ b/src/ezic_date.erl @@ -10,13 +10,14 @@ -export([for/2]). -export([month_to_num/1, day_to_num/1]). --export([compare_times/2, compare_dates/2, compare_datetimes/2]). +-export([compare_times/2, compare_datetimes/2, normalize/1, overlap/2]). -% returns the concrete date tuple for a given rule and year +% returns the concrete date tuple for a given rule and year, irrespective of zone +% e.g. -> {Y,M,D} for(#rule{in=M, on={last, D}}, Y) -> last_day_of(D, Y,M); for(#rule{in=M, on=#tzon{day=Day, filter=Filter}}, Y) -> @@ -29,6 +30,7 @@ last_day_of(Day, Y,M) -> previous_day(Day, {Y,M,LastDay}). +% returns a date tuple {Y,M,D} representing the first available date, given the filter first_day_limited(Day, {geq, N}, Y,M) -> next_day(Day, {Y,M,N}); first_day_limited(Day, {leq, N}, Y,M) -> @@ -99,51 +101,88 @@ day_to_num(_) -> -1. -% returns true if A =< B, false otherwise -compare_datetimes(_, current) -> +compare_datetimes(DT1, DT2) -> + NDT1= normalize(DT1), + NDT2= normalize(DT2), + compare_datetimes_normal(NDT1, NDT2). + + +compare_datetimes_normal(current, _) -> false; +compare_datetimes_normal(_,current) -> true; + +compare_datetimes_normal({D1, T1}, {D2, T2}) when D1 < D2 -> true; -compare_datetimes(current,_) -> +compare_datetimes_normal({D1, T1}, {D2, T2}) when D1 > D2 -> false; - -compare_datetimes(D1={_,_,_}, D2={_,_,_}) -> - compare_dates(D1, D2); - -compare_datetimes(D1={_,_,_}, DT2={_, #tztime{}}) -> - compare_datetimes({D1, #tztime{}}, DT2); - -compare_datetimes(DT1={_, #tztime{}}, D2={_,_,_}) -> - compare_datetimes(DT1, {D2, #tztime{}}); - -compare_datetimes({D1, T1}, {D2, T2}) -> - case compare_dates(D1, D2) of - false -> % D1 > D2 - false; - true -> % D1 =< D2 - case D1 =:= D2 of - false -> % D1 < D2 - true; - true -> % D1 = D2 - compare_times(T1, T2) - end - end. +compare_datetimes_normal({_, T1}, {_, T2}) -> + compare_times(T1, T2). -compare_dates(D1={_,_,_}, D2={_,_,_}) -> - D1 =< D2. - - compare_times(TZ1=#tztime{}, TZ2=#tztime{}) -> - {NT1, NT2} = time_normalize(TZ1, TZ2), + {NT1, NT2} = time_equalize(TZ1, TZ2), NT1 =< NT2; -compare_times(T1, T2) -> - T1 =< T2. +compare_times(Tz1, Tz2) -> + erlang:error(wtf_not_done, [Tz1, Tz2]). -time_normalize(#tztime{time=T1, flag=F1}, #tztime{time=T2, flag=F2}) when F1=:=F2 -> +time_equalize(#tztime{time=T1, flag=F1}, #tztime{time=T2, flag=F2}) when F1=:=F2 -> {T1, T2}; -time_normalize(T1, T2) -> +time_equalize(T1, T2) -> %@todo this may be difficult. gotta do it! erlang:error(wtf_not_done, T1, T2). + +normalize(current) -> current; +normalize(only) -> only; + +normalize(Y) when is_integer(Y) -> + {{Y,1,1}, #tztime{}}; +normalize(Date={_,_,D}) when is_integer(D) -> + {Date, #tztime{}}; +normalize({Y,M,{last, D}}) -> + Date=last_day_of(D, Y,M), + {Date, #tztime{}}; + + +normalize({Date={Y,M,D}, Tz=#tztime{}}) when is_integer(D) -> + {Date, Tz}; +normalize({{Y,M,TzOn=#tzon{day=Day, filter=Filter}}, Tz=#tztime{}}) -> + Date= first_day_limited(Day, Filter, Y,M), + {Date, Tz}; +normalize({{Y,M,{last, D}}, Tz=#tztime{}}) -> + Date=last_day_of(D, Y,M), + {Date, Tz}; +normalize(X) -> + ?debug("normalize: ~p", [X]), + erlang:error(wtf_not_done, X). + + + + +overlap({D1s,D1e}, {D2s,D2e}) -> + D1sN= normalize(D1s), + D1eN= normalize(D1e), + D2sN= normalize(D2s), + D2eN= normalize(D2e), + dates_overlap_normal({D1sN,D1eN}, {D2sN,D2eN}). + + +dates_overlap_normal({D1s,D1e}, {D2s,D2e}) -> + date_between_normal(D1s, {D2s,D2e}) + orelse date_between_normal(D1e, {D2s,D2e}). + + +date_between_normal(only, _) -> false; +date_between_normal(current, {_, current}) -> true; +date_between_normal(current, {_, End}) when End =/= current -> false; +date_between_normal(D1, {D2, only}) -> + {{Y1,_,_},_}=D1, + {{Y2,_,_},_}=D2, + Y1 =:= Y2; +date_between_normal(D1, {D2s, D2e}) -> + compare_datetimes_normal(D2s, D1) + andalso compare_datetimes_normal(D1, D2e). + + diff --git a/test/ezic_date_tests.erl b/test/ezic_date_tests.erl index 0e86404..75414ba 100644 --- a/test/ezic_date_tests.erl +++ b/test/ezic_date_tests.erl @@ -29,7 +29,15 @@ firstlast_day_of_test_() -> compare_datetimes_test_() -> [ - ?_assertEqual(false, ezic_date:compare_datetimes( - {{1997,3,lastSun},{tztime,{1,0,0},u}} + ?_assertNot(ezic_date:compare_datetimes( + {{1997,3,{last, "Sun"}},{tztime,{1,0,0},u}} , {1997,1,1} )) ]. + + +overlap_test_() -> + [ + ?_assert(ezic_date:overlap({1978,only},{{{1977,1,1},#tztime{}}, {{1978,1,1},#tztime{}}})) + , ?_assert(ezic_date:overlap({1978,only},{{{1971,1,1},#tztime{}}, {{1978,1,1},#tztime{}}})) + , ?_assertNot(ezic_date:overlap({1978,only},{{{1971,1,1},#tztime{}}, {{1977,12,31},#tztime{}}})) + ].