源战役
Não pode escolher mais do que 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 

85 linhas
3.7 KiB

%%% -------------------------------------------------------
%%% @author huangyongxing@yeah.net
%%% @doc
%%% 测试计算日期跨度的两种接口效率
%%% @end
%%% -------------------------------------------------------
-module(test_day_span).
-export([
test/1
]).
-include("common.hrl").
%% 测试运行100w次,
%% 结果表明,使用格里高利历天数对比效率更高,大约耗时是另一种方法的70%
%% test_day_span:test(300000).
%% "my calc day_span1" [total: 266(266)ms avg: 0.887(0.887)us]
%% "use gregorian_days" [total: 172(187)ms avg: 0.573(0.623)us]
%% ========================================================================
%% my calc day_span1 = 266.00ms [ 100.00%] 266.00ms [ 100.00%]
%% use gregorian_days = 172.00ms [ 64.66%] 187.00ms [ 70.30%]
%% ========================================================================
test(N) ->
T1 = utime:unixtime(),
T2 = utime:unixtime() - urand:rand(1000000, 9000000),
Fun1 = fun(_) -> day_span1(T1, T2) end,
Fun2 = fun(_) -> day_span2(T1, T2) end,
ptester:run(N, [
{"my calc day_span1", Fun1},
{"use gregorian_days", Fun2}
]).
day_span1(Unixtime1, Unixtime2) ->
get_diff_day(Unixtime1, Unixtime2) + 1.
day_span2(Unixtime1, Unixtime2) ->
{D1, _} = utime:unixtime_to_localtime(Unixtime1),
{D2, _} = utime:unixtime_to_localtime(Unixtime2),
calendar:date_to_gregorian_days(D1) - calendar:date_to_gregorian_days(D2).
%% 原utime中的get_diff_day
%% 早期不兼容夏令时的时候,少一次unixdate及相关调用,测试过比用格里高利历的稍快,
%% 加上针对夏令时的逻辑处理,重新测试结果已经不及格里高利历天数的计算方式)
get_diff_day(Seconds, Seconds) -> 0;
get_diff_day(Seconds1, Seconds2) ->
Midnight1 = utime:unixdate(Seconds1),
Midnight2 = utime:unixdate(Seconds2),
DiffSecs = Midnight1 - Midnight2,
DiffDays = abs(DiffSecs div ?ONE_DAY_SECONDS),
Remainder = DiffSecs rem ?ONE_DAY_SECONDS,
case Remainder =:= 0 of
true -> % 整除意味着两个时刻同处于夏令时、非夏令时或地区无夏令时制
DiffDays;
false -> % 两个时刻中有一个处于夏令时中
%% 由于各地夏令时规定的调整时长不明确,
%% 有半小时有一小时,总之不可能太长,所以以3小时为界。
%% 余数少于3小时说明跨越“结束夏令时”的时间点,应向下取整
%% 余数多于3小时说明跨越“进入夏令时”的时间点,应向上取整
case abs(Remainder) < 10800 of
true -> DiffDays;
false -> DiffDays + 1
end
end.
% %% 此方法存在夏令时问题
% %% 返回结果为两个UNIX时间戳的日期跨度,例如:同一天和相邻2天,返回结果为1和2(而非0和1)
% %% 经测试,与分别使用calendar:date_to_gregorian_days/1转换为两个格里高利历天数进行比较,
% %% 运行30w次,这个方法耗时约0.175秒,转换为格里高历利天数计算约需0.198秒
% get_diff_day(Seconds, Seconds) -> 0;
% get_diff_day(Seconds1, Seconds2) ->
% {_Date, Time} = unixtime_to_localtime(Seconds1),
% DiffSecs = Seconds1 - calendar:time_to_seconds(Time) - Seconds2,
% DiffDays = DiffSecs div ?ONE_DAY_SECONDS,
% Remainder = DiffSecs rem ?ONE_DAY_SECONDS,
% case DiffSecs > 0 of
% true -> % 第一个时间的0点比第二个时间大
% case Remainder =:= 0 of
% true -> 0;
% false -> 1 % 并且不整除(第二个时间非0点),diff days少算了一天,要加1
% end
% + DiffDays;
% false ->
% - DiffDays
% end.