ezic_zone:next/3 was not filtering the Zones to only those after UTCFrom. This may have caused an endless loop, always returning the earliest zone regardless of the progress of time. I wont know; I caught it rather early.
113 lines
2.6 KiB
Erlang
113 lines
2.6 KiB
Erlang
-module(ezic_zone).
|
|
-include("include/ezic.hrl").
|
|
-include_lib("eunit/include/eunit.hrl").
|
|
|
|
-export([
|
|
parse/1
|
|
, current/1
|
|
, current_as_of_utc/2
|
|
, split_by_name/2
|
|
, offset_sec/1
|
|
|
|
, project_end/2
|
|
, project_end_utc/2
|
|
, next/3
|
|
]).
|
|
|
|
|
|
|
|
|
|
parse([Name,GmtOffS,Rule,FormatS | UntilTokens]) ->
|
|
% ?debugVal(GmtOffS),
|
|
GmtOff= ezic_parse:time_val(GmtOffS),
|
|
Until = ezic_parse:until(UntilTokens),
|
|
Format= ezic_parse:tz_abbr(FormatS),
|
|
|
|
{ok, #zone{
|
|
name=Name, gmtoff=GmtOff, rule=Rule,
|
|
format=Format, until=Until
|
|
}}.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
current(TzName) ->
|
|
current_as_of_utc(erlang:universaltime(), TzName).
|
|
|
|
current_as_of_utc(UTCDatetime, TzName) ->
|
|
Zones= ezic_db:zones(TzName),
|
|
get_zone_utc(UTCDatetime, Zones).
|
|
|
|
|
|
|
|
%% returns the active zone for a given utc time
|
|
%% note: requires that flattening be done
|
|
%% this will likely get reworked significantly
|
|
get_zone_utc(_, []) ->
|
|
erlang:error(no_current);
|
|
get_zone_utc(_UTCDatetime, _Zones) ->
|
|
not_done.
|
|
|
|
|
|
|
|
|
|
% returns {[SimilarZone], [DifferentZone]}
|
|
% where Similar Zones are those with the same name as Zone
|
|
% and DifferentZones are all the rest
|
|
split_by_name(#zone{name=N}, Zones) ->
|
|
lists:partition(
|
|
fun(#zone{name=NI}) ->
|
|
N =:= NI
|
|
end
|
|
, Zones).
|
|
|
|
|
|
% @bug doesn't normalize times. Times are self-relative (to standard time), and Now may come from any timezone unless we're careful about that.
|
|
%% older_zone(#zone{until=Until}, UTCDatetime) ->
|
|
%% ezic_date:compare(Until, UTCDatetime).
|
|
|
|
|
|
|
|
offset_sec(Zone) ->
|
|
calendar:time_to_seconds((Zone#zone.gmtoff)#tztime.time).
|
|
|
|
|
|
|
|
|
|
% returns the UTC datetime projected for zone end (given current DST Offset)
|
|
project_end(#zone{until=Until, gmtoff=Offset}, DSTOffset) ->
|
|
ezic_date:all_times(Until, Offset, DSTOffset).
|
|
|
|
% returns just the UTC datetime projected for zone end
|
|
project_end_utc(Zone=#zone{}, DSTOffset) ->
|
|
{_,_,UTCDatetime}= project_end(Zone, DSTOffset),
|
|
UTCDatetime.
|
|
|
|
|
|
|
|
|
|
% returns {Zone, Rest} where Zone is the next zone after UTCFrom,
|
|
% subject to the DST offset.
|
|
% Note that dst differences *can* change which zone comes next,
|
|
% though it's very unlikely (and does not exist in the current tz database files).
|
|
% this method covers that event, anyhow.
|
|
|
|
%% BAD!!! UCTFrom is not used!
|
|
next(ZoneList, UTCFrom, DSTOff) ->
|
|
DatedList= lists:map(
|
|
fun(Z=#zone{until=Until, gmtoff=Offset})->
|
|
NUntil= ezic_date:normalize(Until),
|
|
{_,_,UTCDt}= ezic_date:all_times(NUntil, Offset, DSTOff),
|
|
{UTCDt, Z}
|
|
end
|
|
, ZoneList),
|
|
FilteredList= lists:filter(fun({IDt,_})-> UTCFrom =< IDt end, DatedList),
|
|
SortedList= lists:sort(FilteredList),
|
|
[Z || {_,Z}<- SortedList].
|