Costa Rica's flatzones aren't processed after 1992. Gotta check her out.
This commit is contained in:
7
Makefile
7
Makefile
@@ -1,7 +1,7 @@
|
|||||||
ERLC_WARNINGS := -W1
|
ERLC_WARNINGS := -W1
|
||||||
MNESIA_DIR := db
|
MNESIA_DIR := db
|
||||||
RUN_INIT := -run ezic_db init
|
RUN_INIT := -run ezic_db init
|
||||||
DEBUG := -DNODEBUG
|
DEBUG := -DNODEBUG -Ddebug
|
||||||
TEST :=
|
TEST :=
|
||||||
TZSET := northamerica
|
TZSET := northamerica
|
||||||
SHELL := /bin/bash
|
SHELL := /bin/bash
|
||||||
@@ -33,7 +33,7 @@ run :
|
|||||||
erl -pa ebin -mnesia dir $(MNESIA_DIR) $(RUN_INIT)
|
erl -pa ebin -mnesia dir $(MNESIA_DIR) $(RUN_INIT)
|
||||||
|
|
||||||
|
|
||||||
devstart : RUN_INIT := $(RUN_INIT) -s ezic dev_start -s erlang halt
|
devstart : RUN_INIT += -s ezic dev -s erlang halt
|
||||||
devstart : all run
|
devstart : all run
|
||||||
|
|
||||||
|
|
||||||
@@ -46,4 +46,5 @@ diff :
|
|||||||
emacs /tmp/ezic.tmp.diff
|
emacs /tmp/ezic.tmp.diff
|
||||||
|
|
||||||
|
|
||||||
debug : DEBUG := +debug_info -dNODEBUG
|
debug : DEBUG += +debug_info
|
||||||
|
debug : all run
|
||||||
26
src/ezic.erl
26
src/ezic.erl
@@ -8,7 +8,7 @@
|
|||||||
, next_timechange_after/2
|
, next_timechange_after/2
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-export([load/1, dev_start/0, test/0]).
|
-export([load/1, dev/0, test/0]).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -21,10 +21,16 @@
|
|||||||
localtime(TzName) ->
|
localtime(TzName) ->
|
||||||
utc_to_local(erlang:universaltime(), TzName).
|
utc_to_local(erlang:universaltime(), TzName).
|
||||||
|
|
||||||
|
%% utc_to_local(UTCDatetime, TzName) ->
|
||||||
|
%% {ok, Zone, Rule}= current_as_of_utc(UTCDatetime, TzName),
|
||||||
|
%% SecDiff= time_offset(Zone, Rule),
|
||||||
|
%% ezic_date:add_seconds(UTCDatetime, SecDiff).
|
||||||
|
|
||||||
|
|
||||||
utc_to_local(UTCDatetime, TzName) ->
|
utc_to_local(UTCDatetime, TzName) ->
|
||||||
{ok, Zone, Rule}= current_as_of_utc(UTCDatetime, TzName),
|
#flatzone{offset=Offset, dstoffset=DSTOffset}= ezic_db:flatzone(UTCDatetime, TzName),
|
||||||
SecDiff= time_offset(Zone, Rule),
|
ezic_date:add_offset(ezic_date:add_offset(UTCDatetime, Offset), DSTOffset).
|
||||||
ezic_date:add_seconds(UTCDatetime, SecDiff).
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -48,11 +54,13 @@ load(Folder) ->
|
|||||||
ezic_loader:load(Folder).
|
ezic_loader:load(Folder).
|
||||||
|
|
||||||
|
|
||||||
dev_start() ->
|
dev() ->
|
||||||
% ezic:load(filename:join("priv","tzdata")),
|
ezic:load(filename:join("priv","tzdata")),
|
||||||
% ezic_flatten:flatten().
|
ezic_flatten:flatten(),
|
||||||
TZones= ezic_db:zones("Africa/Tripoli"),
|
% Zones= ezic_db:zones("WET"),
|
||||||
ezic_flatten:flatten_all_zones(TZones).
|
% ezic_flatten:flatten_all_zones(Zones),
|
||||||
|
|
||||||
|
ok.
|
||||||
|
|
||||||
|
|
||||||
test() ->
|
test() ->
|
||||||
|
|||||||
@@ -47,13 +47,12 @@ normalize(A) when is_atom(A) ->
|
|||||||
A;
|
A;
|
||||||
normalize(Y) when is_integer(Y) ->
|
normalize(Y) when is_integer(Y) ->
|
||||||
{{Y,1,1}, #tztime{}};
|
{{Y,1,1}, #tztime{}};
|
||||||
normalize(Date={Y,M,D})
|
normalize({Y,M,D}) ->
|
||||||
when is_integer(Y), is_integer(M), is_integer(D) ->
|
{relative_date(Y,M,D), #tztime{}};
|
||||||
{Date, #tztime{}};
|
normalize({{Y,M,D}, T=#tztime{}}) ->
|
||||||
normalize(R={{_,_,_}, #tztime{}}) ->
|
{relative_date(Y,M,D), T};
|
||||||
R;
|
normalize({{Y,M,D}, T={_,_,_}}) ->
|
||||||
normalize({D={_,_,_}, T={_,_,_}}) ->
|
{relative_date(Y,M,D), #tztime{time=T}}.
|
||||||
{D, #tztime{time=T}}.
|
|
||||||
|
|
||||||
|
|
||||||
%% normalizes a date, and sets the #tztime{flag=Flag} if appropriate
|
%% normalizes a date, and sets the #tztime{flag=Flag} if appropriate
|
||||||
@@ -76,23 +75,26 @@ normalize(D, Flag) ->
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
%% returns RELATIVE datetime for a rule and Year
|
%% returns RELATIVE datetime for a rule and Year
|
||||||
%% -> {{Y,M,D},#tztime{}} | {{Y,M,D},{HH,MM,SS}}
|
%% -> {{Y,M,D},#tztime{}} | {{Y,M,D},{HH,MM,SS}}
|
||||||
for_rule_relative(#rule{in=M, on=D, at=At}, Y) when is_integer(D) ->
|
for_rule_relative(#rule{in=M, on=D, at=At}, Y) ->
|
||||||
{{Y,M,D}, At};
|
{relative_date(Y,M,D), At}.
|
||||||
for_rule_relative(#rule{in=M, on={last, D}, at=At}, Y) ->
|
|
||||||
{last_day_of(D, Y,M), At};
|
|
||||||
for_rule_relative(#rule{in=M, on=#tzon{day=Day, filter=Filter}, at=At}, Y) ->
|
|
||||||
{first_day_limited(Day, Filter, Y,M), At}.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
relative_date(Y,M,D) when is_integer(D) ->
|
||||||
|
{Y,M,D};
|
||||||
|
relative_date(Y,M,{last, D}) ->
|
||||||
|
last_day_of(D, Y,M);
|
||||||
|
relative_date(Y,M,#tzon{day=Day, filter=Filter}) ->
|
||||||
|
first_day_limited(Day, Filter, Y,M).
|
||||||
|
|
||||||
|
|
||||||
%% returns set of ALL datetimes for a rule, given the gmt offset and
|
%% returns set of ALL datetimes for a rule, given the gmt offset and
|
||||||
%% current dst offset.
|
%% current dst offset.
|
||||||
%% @bug @todo Year is ambiguous. In the case of Africa/Tripoli, a jan 1st, 1952 rule shows up as 1951 due to offset and dst.
|
%% @bug @todo Year is ambiguous. In the case of Africa/Tripoli, a jan 1st, 1952 rule shows up as 1951 due to offset and dst
|
||||||
for_rule(Rule, Offset, PrevDSTOffset, NextDSTOffset, Year) ->
|
for_rule(Rule, Offset, PrevDSTOffset, NextDSTOffset, Year) ->
|
||||||
{WT,ST,UT}= for_rule_old_dst(Rule, Offset, PrevDSTOffset, Year),
|
{WT,ST,UT}= for_rule_old_dst(Rule, Offset, PrevDSTOffset, Year),
|
||||||
WTNew= add_offset(WT, PrevDSTOffset, NextDSTOffset),
|
WTNew= add_offset(WT, PrevDSTOffset, NextDSTOffset),
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
-include_lib("eunit/include/eunit.hrl").
|
-include_lib("eunit/include/eunit.hrl").
|
||||||
|
|
||||||
|
|
||||||
-export([zones/1, rules/1]).
|
-export([zones/1, rules/1, flatzones/1, flatzone/2]).
|
||||||
-export([wipe/0, init/0, insert_all/1, get_all/1]).
|
-export([wipe/0, init/0, insert_all/1, get_all/1]).
|
||||||
|
|
||||||
|
|
||||||
@@ -51,6 +51,29 @@ get_all(Tab) when is_atom(Tab) ->
|
|||||||
Ret.
|
Ret.
|
||||||
|
|
||||||
|
|
||||||
|
flatzones(TzName) ->
|
||||||
|
F = fun() ->
|
||||||
|
Q = qlc:q([Fz || Fz=#flatzone{tzname=N}<- mnesia:table(flatzone), N=:=TzName]),
|
||||||
|
qlc:e(Q)
|
||||||
|
end,
|
||||||
|
{atomic, Ret}= mnesia:transaction(F),
|
||||||
|
Ret.
|
||||||
|
|
||||||
|
|
||||||
|
flatzone(Date, TzName) ->
|
||||||
|
F = fun()->
|
||||||
|
Q = qlc:q(
|
||||||
|
[Fz || Fz=#flatzone{tzname=N, utc_from=UF, utc_to=UT} <- mnesia:table(flatzone)
|
||||||
|
, N=:=TzName
|
||||||
|
, ezic_date:compare(UF, Date)
|
||||||
|
, ezic_date:compare(Date, UT)]),
|
||||||
|
qlc:e(Q)
|
||||||
|
end,
|
||||||
|
{atomic, [FlatZone]}= mnesia:transaction(F),
|
||||||
|
FlatZone.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
% WRITE - insertion/edit methods
|
% WRITE - insertion/edit methods
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
@@ -76,7 +99,7 @@ insert_all(Records) ->
|
|||||||
% initialize the db
|
% initialize the db
|
||||||
init() ->
|
init() ->
|
||||||
create_tabs(mnesia:create_schema([node()])),
|
create_tabs(mnesia:create_schema([node()])),
|
||||||
mnesia:wait_for_tables([rule, zone, link, leap], 3000).
|
mnesia:wait_for_tables([rule, zone, link, leap, flatzone], 3000).
|
||||||
|
|
||||||
|
|
||||||
% WARNING: deletes all db files
|
% WARNING: deletes all db files
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ flatten() ->
|
|||||||
flatten_all_zones([]) ->
|
flatten_all_zones([]) ->
|
||||||
done;
|
done;
|
||||||
flatten_all_zones([Z1|_]= AllZones) ->
|
flatten_all_zones([Z1|_]= AllZones) ->
|
||||||
|
io:format("Flattening zones: ~s~n", [Z1#zone.name]),
|
||||||
{CurrentZones, RestZones}= ezic_zone:split_by_name(Z1, AllZones),
|
{CurrentZones, RestZones}= ezic_zone:split_by_name(Z1, AllZones),
|
||||||
|
|
||||||
Flats= flatten_zone_set(CurrentZones),
|
Flats= flatten_zone_set(CurrentZones),
|
||||||
@@ -71,7 +72,7 @@ flatten_zone_set(FromTimeStub=#flatzone{utc_from=UTCFrom, dstoffset=DSTOffset}
|
|||||||
, CurrentRule) ->
|
, CurrentRule) ->
|
||||||
|
|
||||||
[Zone | RestZones] = ezic_zone:next(Zones, UTCFrom, DSTOffset),
|
[Zone | RestZones] = ezic_zone:next(Zones, UTCFrom, DSTOffset),
|
||||||
#zone{rule=RuleName, until=_UntilTime, gmtoff=Offset}= Zone,
|
#zone{rule=RuleName}= Zone,
|
||||||
|
|
||||||
?debugVal(Zone),
|
?debugVal(Zone),
|
||||||
|
|
||||||
@@ -106,12 +107,17 @@ flatten_zone_set(FromTimeStub=#flatzone{utc_from=UTCFrom, dstoffset=DSTOffset}
|
|||||||
|
|
||||||
%% return flats if we've exceeded our years, or recurse if we can keep going
|
%% return flats if we've exceeded our years, or recurse if we can keep going
|
||||||
NFUTCFrom = NextFlat#flatzone.utc_from,
|
NFUTCFrom = NextFlat#flatzone.utc_from,
|
||||||
case maxyear_reached(NFUTCFrom) of
|
try maxyear_reached(NFUTCFrom) of
|
||||||
true ->
|
true ->
|
||||||
?debugMsg("maxyear reached from flatten_zone_set"),
|
?debugMsg("maxyear reached from flatten_zone_set"),
|
||||||
FinalFlats;
|
FinalFlats;
|
||||||
false ->
|
false ->
|
||||||
flatten_zone_set(NextFlat, RestZones, FinalFlats, EndingRule)
|
flatten_zone_set(NextFlat, RestZones, FinalFlats, EndingRule)
|
||||||
|
catch
|
||||||
|
exit:Reason ->
|
||||||
|
?debugMsg("bad year for nextflat:"),
|
||||||
|
?debugVal(NextFlat),
|
||||||
|
erlang:error(Reason)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
@@ -122,20 +128,24 @@ flatten_rule_set(FlatStart=#flatzone{utc_from=UTCFrom, dstoffset=DSTOffset, offs
|
|||||||
, Zone, Rules, CurrentRule, Flats) ->
|
, Zone, Rules, CurrentRule, Flats) ->
|
||||||
|
|
||||||
|
|
||||||
|
?debugVal(Offset),
|
||||||
|
?debugVal(DSTOffset),
|
||||||
|
?debugVal(UTCFrom),
|
||||||
|
|
||||||
ValidRules= lists:delete(CurrentRule, Rules),
|
ValidRules= lists:delete(CurrentRule, Rules),
|
||||||
RulesWithDates= lists:foldl(
|
RulesWithDates= lists:foldl(
|
||||||
fun(R, Acc)->
|
fun(R, Acc)->
|
||||||
case ezic_rule:project_next(R, Offset, DSTOffset, UTCFrom) of
|
case ezic_rule:project_next(R, Offset, DSTOffset, UTCFrom) of
|
||||||
none -> Acc;
|
none -> Acc;
|
||||||
D -> [{D,R} | Acc]
|
{Year, D} -> [{D,Year, R} | Acc]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
,[], ValidRules),
|
,[], ValidRules),
|
||||||
|
|
||||||
|
|
||||||
{UTCEndingRuleDate, EndingRule}=
|
{UTCEndingRuleDate, EndingRuleYear, EndingRule}=
|
||||||
case length(RulesWithDates) > 0 of
|
case length(RulesWithDates) > 0 of
|
||||||
false -> {maximum, none};
|
false -> {maximum, maximum, none};
|
||||||
true -> hd(lists:sort(RulesWithDates))
|
true -> hd(lists:sort(RulesWithDates))
|
||||||
end,
|
end,
|
||||||
|
|
||||||
@@ -143,10 +153,12 @@ flatten_rule_set(FlatStart=#flatzone{utc_from=UTCFrom, dstoffset=DSTOffset, offs
|
|||||||
|
|
||||||
|
|
||||||
?debugVal(UTCEndingRuleDate),
|
?debugVal(UTCEndingRuleDate),
|
||||||
|
?debugVal(EndingRuleYear),
|
||||||
|
?debugVal(EndingRule),
|
||||||
?debugVal(ZoneDate),
|
?debugVal(ZoneDate),
|
||||||
|
|
||||||
|
|
||||||
case maxyear_reached(UTCEndingRuleDate) andalso maxyear_reached(ZoneDate) of
|
try maxyear_reached(UTCEndingRuleDate) andalso maxyear_reached(ZoneDate) of
|
||||||
true ->
|
true ->
|
||||||
?debugMsg("maxyear reached from flatten_rule_set"),
|
?debugMsg("maxyear reached from flatten_rule_set"),
|
||||||
{Flats, #flatzone{utc_from=maximum}, none};
|
{Flats, #flatzone{utc_from=maximum}, none};
|
||||||
@@ -155,7 +167,7 @@ flatten_rule_set(FlatStart=#flatzone{utc_from=UTCFrom, dstoffset=DSTOffset, offs
|
|||||||
case ezic_date:compare(ZoneDate, UTCEndingRuleDate) of
|
case ezic_date:compare(ZoneDate, UTCEndingRuleDate) of
|
||||||
false ->
|
false ->
|
||||||
%% same zone, new rule
|
%% same zone, new rule
|
||||||
{EndFlat, NextFlat}= finish_and_start_flat(FlatStart, EndingRule, UTCEndingRuleDate),
|
{EndFlat, NextFlat}= finish_and_start_flat(FlatStart, EndingRule, EndingRuleYear),
|
||||||
NewFlats= [EndFlat | Flats],
|
NewFlats= [EndFlat | Flats],
|
||||||
flatten_rule_set(NextFlat, Zone, Rules, EndingRule, NewFlats);
|
flatten_rule_set(NextFlat, Zone, Rules, EndingRule, NewFlats);
|
||||||
true ->
|
true ->
|
||||||
@@ -171,6 +183,10 @@ flatten_rule_set(FlatStart=#flatzone{utc_from=UTCFrom, dstoffset=DSTOffset, offs
|
|||||||
{[IEF | Flats], INF, EndingRule}
|
{[IEF | Flats], INF, EndingRule}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
catch
|
||||||
|
error:{bad_year,Val} ->
|
||||||
|
io:format("bad year for EndingRule: ~p~n", [EndingRule]),
|
||||||
|
erlang:error(bad_year, Val)
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
@@ -179,10 +195,10 @@ flatten_rule_set(FlatStart=#flatzone{utc_from=UTCFrom, dstoffset=DSTOffset, offs
|
|||||||
%% rule is ending, while timezone remains
|
%% rule is ending, while timezone remains
|
||||||
finish_and_start_flat(FlatStub=#flatzone{offset=Offset, dstoffset=OldDSTOffset}
|
finish_and_start_flat(FlatStub=#flatzone{offset=Offset, dstoffset=OldDSTOffset}
|
||||||
, NewRule=#rule{save=NewDSTSave}
|
, NewRule=#rule{save=NewDSTSave}
|
||||||
, _EndingRuleDate={{ERDY,_,_},_}) ->
|
, EndingRuleYear) ->
|
||||||
|
|
||||||
%% @todo for_rule_all was already called in a loop earlier. use those values instead.
|
%% @todo for_rule_all was already called in a loop earlier. use those values instead.
|
||||||
{{WD, WDn}, SD, UD}= ezic_date:for_rule(NewRule, Offset, OldDSTOffset, NewDSTSave, ERDY),
|
{{WD, WDn}, SD, UD}= ezic_date:for_rule(NewRule, Offset, OldDSTOffset, NewDSTSave, EndingRuleYear),
|
||||||
{WDm, SDm, UDm}= ezic_date:m1s({WD, SD, UD}),
|
{WDm, SDm, UDm}= ezic_date:m1s({WD, SD, UD}),
|
||||||
|
|
||||||
EndFlat= ?ENDFLAT(FlatStub, WDm, SDm, UDm, OldDSTOffset),
|
EndFlat= ?ENDFLAT(FlatStub, WDm, SDm, UDm, OldDSTOffset),
|
||||||
@@ -202,7 +218,7 @@ finish_and_start_flat(FlatStub=#flatzone{offset=Offset, dstoffset=OldDSTOffset}
|
|||||||
%% the next zone with the current DST offset and the UTC start
|
%% the next zone with the current DST offset and the UTC start
|
||||||
%% datetime
|
%% datetime
|
||||||
finish_and_start_flat(FlatStub=#flatzone{}, Zone=#zone{}, EndingDST) ->
|
finish_and_start_flat(FlatStub=#flatzone{}, Zone=#zone{}, EndingDST) ->
|
||||||
EndDatesP1={WD,SD,UD}= ezic_zone:project_end(Zone, EndingDST),
|
EndDatesP1={_,_,UD}= ezic_zone:project_end(Zone, EndingDST),
|
||||||
{WDm, SDm, UDm}= ezic_date:m1s(EndDatesP1),
|
{WDm, SDm, UDm}= ezic_date:m1s(EndDatesP1),
|
||||||
EndFlat= ?ENDFLAT(FlatStub, WDm, SDm, UDm, EndingDST),
|
EndFlat= ?ENDFLAT(FlatStub, WDm, SDm, UDm, EndingDST),
|
||||||
|
|
||||||
@@ -218,7 +234,7 @@ finish_and_start_flat(FlatStub=#flatzone{}, Zone=#zone{}, EndingDST) ->
|
|||||||
finish_flatzone_both(FlatStub=#flatzone{}, EndingZone=#zone{}, ChangingRule=#rule{save=NewDST}, EndingDST) ->
|
finish_flatzone_both(FlatStub=#flatzone{}, EndingZone=#zone{}, ChangingRule=#rule{save=NewDST}, EndingDST) ->
|
||||||
?debugVal(FlatStub),
|
?debugVal(FlatStub),
|
||||||
|
|
||||||
EndDatesP1={WD,SD,UD}= ezic_zone:project_end(EndingZone, EndingDST),
|
EndDatesP1={_,_,UD}= ezic_zone:project_end(EndingZone, EndingDST),
|
||||||
{WDm, SDm, UDm}= ezic_date:m1s(EndDatesP1),
|
{WDm, SDm, UDm}= ezic_date:m1s(EndDatesP1),
|
||||||
EndFlat= ?ENDFLAT(FlatStub, WDm, SDm, UDm, EndingDST),
|
EndFlat= ?ENDFLAT(FlatStub, WDm, SDm, UDm, EndingDST),
|
||||||
|
|
||||||
@@ -231,10 +247,10 @@ finish_flatzone_both(FlatStub=#flatzone{}, EndingZone=#zone{}, ChangingRule=#rul
|
|||||||
|
|
||||||
populate_flatzone(
|
populate_flatzone(
|
||||||
FZ=#flatzone{utc_from=UTCFrom, dstoffset=DSTOffset}
|
FZ=#flatzone{utc_from=UTCFrom, dstoffset=DSTOffset}
|
||||||
, Zone=#zone{name=Name, gmtoff=Offset}) ->
|
, #zone{name=Name, gmtoff=Offset}) ->
|
||||||
|
|
||||||
UTCFromTZ= ezic_date:normalize(UTCFrom, u),
|
UTCFromTZ= ezic_date:normalize(UTCFrom, u),
|
||||||
{WT, ST, UTCFRom}= ezic_date:all_times(UTCFromTZ, Offset, DSTOffset),
|
{WT, ST, _}= ezic_date:all_times(UTCFromTZ, Offset, DSTOffset),
|
||||||
FZ#flatzone{offset=Offset, tzname=Name, wall_from=WT, std_from=ST}.
|
FZ#flatzone{offset=Offset, tzname=Name, wall_from=WT, std_from=ST}.
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -25,16 +25,20 @@ parse([Name,FromS,ToS,_Type,InS,OnS,AtS,SaveS,Letters]) ->
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
% returns the projected date of the next "rule event" in UTC time,
|
% returns {Year, UTCDate} where UTCDate is the projected date of the
|
||||||
% after the given UTCDatetime, with the given the zone Offset and current DST offset.
|
% next "rule event" in UTC time, after the given UTCDatetime, with the
|
||||||
|
% given the zone Offset and current DST offset, and Year is the rule
|
||||||
|
% year (which may differ from the UTC year).
|
||||||
project_next(Rule=#rule{from=RFrom}, Offset, DSTOffset, minimum) ->
|
project_next(Rule=#rule{from=RFrom}, Offset, DSTOffset, minimum) ->
|
||||||
ezic_date:for_rule_utc(Rule, Offset, DSTOffset, RFrom);
|
RetDate={{RetYear,_,_},_}= ezic_date:for_rule_utc(Rule, Offset, DSTOffset, RFrom),
|
||||||
|
{RetYear, RetDate};
|
||||||
project_next(Rule=#rule{}, Offset, DSTOff, UTCAfter={{AY,_,_},_}) ->
|
project_next(Rule=#rule{}, Offset, DSTOff, UTCAfter={{AY,_,_},_}) ->
|
||||||
YearRange= years(Rule),
|
YearRange= years(Rule),
|
||||||
GoodYears= years_after(AY, YearRange),
|
GoodYears= years_after(AY, YearRange),
|
||||||
project_next2(Rule, Offset, UTCAfter, DSTOff, GoodYears).
|
project_next2(Rule, Offset, UTCAfter, DSTOff, GoodYears).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
% PRIVATE
|
% PRIVATE
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
@@ -71,7 +75,7 @@ project_next2(_,_,_,_,none) ->
|
|||||||
project_next2(Rule, Offset, UTCAfter, DSTOffset, Years={FromYear, _}) ->
|
project_next2(Rule, Offset, UTCAfter, DSTOffset, Years={FromYear, _}) ->
|
||||||
RuleDate= ezic_date:for_rule_utc(Rule, Offset, DSTOffset, FromYear),
|
RuleDate= ezic_date:for_rule_utc(Rule, Offset, DSTOffset, FromYear),
|
||||||
case ezic_date:compare(UTCAfter, RuleDate) andalso (not ezic_date:equal(UTCAfter, RuleDate)) of
|
case ezic_date:compare(UTCAfter, RuleDate) andalso (not ezic_date:equal(UTCAfter, RuleDate)) of
|
||||||
true -> RuleDate;
|
true -> {FromYear, RuleDate};
|
||||||
false ->
|
false ->
|
||||||
RestYears= years_after(FromYear+1, Years),
|
RestYears= years_after(FromYear+1, Years),
|
||||||
project_next2(Rule, Offset, UTCAfter, DSTOffset, RestYears)
|
project_next2(Rule, Offset, UTCAfter, DSTOffset, RestYears)
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ project_end(#zone{until=Until, gmtoff=Offset}, DSTOffset) ->
|
|||||||
NUntil= ezic_date:normalize(Until),
|
NUntil= ezic_date:normalize(Until),
|
||||||
ezic_date:all_times(NUntil, Offset, DSTOffset).
|
ezic_date:all_times(NUntil, Offset, DSTOffset).
|
||||||
|
|
||||||
|
|
||||||
% returns just the UTC datetime projected for zone end
|
% returns just the UTC datetime projected for zone end
|
||||||
project_end_utc(Zone=#zone{}, DSTOffset) ->
|
project_end_utc(Zone=#zone{}, DSTOffset) ->
|
||||||
% ?debugVal(Zone),
|
% ?debugVal(Zone),
|
||||||
|
|||||||
@@ -55,10 +55,10 @@ for_rule_test_() ->
|
|||||||
, ?_assertEqual({
|
, ?_assertEqual({
|
||||||
{ {{1952,1,1},{0,0,0}}, {{1951,12,31},{23,0,0}} }, % {oldDst, newDst}
|
{ {{1952,1,1},{0,0,0}}, {{1951,12,31},{23,0,0}} }, % {oldDst, newDst}
|
||||||
{{1951,12,31},{23,0,0}},
|
{{1951,12,31},{23,0,0}},
|
||||||
{{1951,12,31},{23,0,0}} },
|
{{1951,12,31},{22,0,0}} },
|
||||||
ezic_date:for_rule(
|
ezic_date:for_rule(
|
||||||
#rule{from=1952, to=only, in=1, on=1, at=#tztime{}, save={0,0,0}},
|
#rule{from=1952, to=only, in=1, on=1, at=#tztime{}, save={0,0,0}},
|
||||||
{1,0,0}, {1,0,0}, {0,0,0}, 1951))
|
{1,0,0}, {1,0,0}, {0,0,0}, 1952))
|
||||||
|
|
||||||
].
|
].
|
||||||
|
|
||||||
@@ -96,3 +96,21 @@ all_times_test_() ->
|
|||||||
{{Date,{9,2,0}}, {Date,{8,2,0}}, {Date,{16,2,0}}}
|
{{Date,{9,2,0}}, {Date,{8,2,0}}, {Date,{16,2,0}}}
|
||||||
, ezic_date:all_times({Date,UTC}, {-8,0,0}, {1,0,0}))
|
, ezic_date:all_times({Date,UTC}, {-8,0,0}, {1,0,0}))
|
||||||
].
|
].
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
normalize_test_() ->
|
||||||
|
TZT= #tztime{time={1,2,3}, flag=s},
|
||||||
|
[
|
||||||
|
?_assertEqual({{2010,1,1}, #tztime{}}, ezic_date:normalize(2010))
|
||||||
|
, ?_assertEqual({{2010,2,3}, #tztime{}}, ezic_date:normalize({2010,2,3}))
|
||||||
|
, ?_assertEqual({{2010,11,28}, #tztime{}}, ezic_date:normalize({2010,11,{last, "Sun"}}))
|
||||||
|
, ?_assertEqual({{2010,11,16}, #tztime{}}, ezic_date:normalize({2010,11,#tzon{day="Tue", filter={geq, 10}}}))
|
||||||
|
|
||||||
|
, ?_assertError(function_clause, ezic_date:normalize({2010, #tztime{}}))
|
||||||
|
|
||||||
|
, ?_assertEqual({{2010,2,3}, TZT}, ezic_date:normalize({{2010,2,3}, TZT}))
|
||||||
|
, ?_assertEqual({{2010,11,28}, TZT}, ezic_date:normalize({{2010,11,{last, "Sun"}}, TZT}))
|
||||||
|
, ?_assertEqual({{2010,11,16}, TZT}, ezic_date:normalize({{2010,11,#tzon{day="Tue", filter={geq, 10}}}, TZT}))
|
||||||
|
|
||||||
|
].
|
||||||
|
|||||||
@@ -7,21 +7,21 @@ project_next_test_() ->
|
|||||||
[
|
[
|
||||||
|
|
||||||
% simple UTC example
|
% simple UTC example
|
||||||
?_assertEqual({{2010,11,10},{16,20,0}},
|
?_assertEqual({2010, {{2010,11,10},{16,20,0}}},
|
||||||
ezic_rule:project_next(
|
ezic_rule:project_next(
|
||||||
#rule{from=1984, to=2032, in=11, on=10, at=#tztime{time={16,20,0}, flag=u}}
|
#rule{from=1984, to=2032, in=11, on=10, at=#tztime{time={16,20,0}, flag=u}}
|
||||||
, {-5,0,0}, {-1,0,0}, {{2010,11,10},{0,0,0}}
|
, {-5,0,0}, {-1,0,0}, {{2010,11,10},{0,0,0}}
|
||||||
))
|
))
|
||||||
|
|
||||||
% skip a year UTC example
|
% skip a year UTC example
|
||||||
, ?_assertEqual({{2011,11,10},{16,20,0}},
|
, ?_assertEqual({2011, {{2011,11,10},{16,20,0}}},
|
||||||
ezic_rule:project_next(
|
ezic_rule:project_next(
|
||||||
#rule{from=1984, to=2032, in=11, on=10, at=#tztime{time={16,20,0}, flag=u}}
|
#rule{from=1984, to=2032, in=11, on=10, at=#tztime{time={16,20,0}, flag=u}}
|
||||||
, {-5,0,0}, {-1,0,0}, {{2010,11,10},{16,21,0}}
|
, {-5,0,0}, {-1,0,0}, {{2010,11,10},{16,21,0}}
|
||||||
))
|
))
|
||||||
|
|
||||||
% skip 3 years UTC example
|
% skip 3 years UTC example
|
||||||
, ?_assertEqual({{2013,11,10},{16,20,0}},
|
, ?_assertEqual({2013, {{2013,11,10},{16,20,0}}},
|
||||||
ezic_rule:project_next(
|
ezic_rule:project_next(
|
||||||
#rule{from=1984, to=2032, in=11, on=10, at=#tztime{time={16,20,0}, flag=u}}
|
#rule{from=1984, to=2032, in=11, on=10, at=#tztime{time={16,20,0}, flag=u}}
|
||||||
, {-5,0,0}, {-1,0,0}, {{2012,11,11},{16,20,0}}
|
, {-5,0,0}, {-1,0,0}, {{2012,11,11},{16,20,0}}
|
||||||
@@ -34,4 +34,11 @@ project_next_test_() ->
|
|||||||
, {-5,0,0}, {-1,0,0}, {{2012,11,11},{16,20,0}}
|
, {-5,0,0}, {-1,0,0}, {{2012,11,11},{16,20,0}}
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
||||||
|
% wacky UTC/DST mismatch example for Africa/Tripoli
|
||||||
|
, ?_assertEqual({1952, {{1951,12,31},{22,0,0}}},
|
||||||
|
ezic_rule:project_next(
|
||||||
|
#rule{from=1952, to=only, in=1, on=1, at=#tztime{}, save={0,0,0}}
|
||||||
|
, {1,0,0}, {1,0,0}, {{1951,10,14},{3,0,0}}
|
||||||
|
))
|
||||||
].
|
].
|
||||||
|
|||||||
Reference in New Issue
Block a user