%%% -------------------------------------------------------
%%% @author huangyongxing@yeah.net
%%% @doc
%%% 测试中，utime_old_xxxx是直接用ONE_DAY_SECONDS来运算时间的，对
%%% 夏令时支持不友好（其他相关接口可查svn历史中的utime模块）
%%% utime是更新之后，尽量支持夏令时的相关接口模块
%%%
%%% 注意：实际每次测试都跑N次（样本数据有N个，以更准确观察数据情况）
%%% 所以函数实际的单次运行时间，应该除以样本数
%%% 样本数为1-1000之间，如果输入错误会修正为100。
%%% 测试次数也要考虑样本数量，避免输入过大的测试次数。
%%% @end
%%% -------------------------------------------------------
-module(test_utime).
-export([
        test_lc_to_unix/2
        ,test_unix_to_lc/2
        ,test_unix_week/2
    ]).

%% 测试localtime转unixtime时间戳
%% 结论是效率大体相当，有微弱下降。基本无影响
%% LocalTime to unixtime
% ------------------------------------------------------------------------
% test_utime:test_lc_to_unix(10000, 1000). 
% "utime new" [total: 2450(2452)ms avg: 245.000(245.200)us]
% "utime old" [total: 2450(2451)ms avg: 245.000(245.100)us]
% ========================================================================
%            utime new =   2450.00ms [  100.00%]   2452.00ms [  100.00%]
%            utime old =   2450.00ms [  100.00%]   2451.00ms [   99.96%]
% ========================================================================
test_lc_to_unix(Times, DataN) ->
    FunDateTime = fun() ->
            Secs = urand:rand(1000, 100000),
            Unixtime = utime:unixtime() + Secs,
            utime:unixtime_to_localtime(Unixtime)
    end,
    N = fix_data_n(DataN),
    DateTimeList = [ FunDateTime() || _<-lists:seq(1, N)],
    ptester:run(Times, [
            {"utime new", fun(_) -> each(fun(DT) -> utime:unixtime(DT) end, DateTimeList) end},
            {"utime old", fun(_) -> each(fun(DT) -> utime_old_unixtime(DT) end, DateTimeList) end}
        ]),
    ok.

%% 测试unixtime时间戳转localtime
%% 结论是效率有一定程度下降，时间消耗大约为原接口的1.2倍。可以接受
%% unixtime to localtime
% ------------------------------------------------------------------------
% test_utime:test_unix_to_lc(10000, 1000).
% "utime new" [total: 1880(1884)ms avg: 188.000(188.400)us]
% "utime old" [total: 1560(1571)ms avg: 156.000(157.100)us]
% ========================================================================
%            utime new =   1880.00ms [  100.00%]   1884.00ms [  100.00%]
%            utime old =   1560.00ms [   82.98%]   1571.00ms [   83.39%]
% ========================================================================
test_unix_to_lc(Times, DataN) ->
    FunTime = fun() ->
            Secs = urand:rand(1000, 100000),
            utime:unixtime() + Secs
    end,
    N = fix_data_n(DataN),
    TimeList = [ FunTime() || _<-lists:seq(1, N)],
    ptester:run(Times, [
            {"utime new", fun(_) -> each(fun(T) -> utime:unixtime_to_localtime(T) end, TimeList) end},
            {"utime old", fun(_) -> each(fun(T) -> utime_old_unixtime_to_localtime(T) end, TimeList) end}
        ]),
    ok.

%% 测试unixtime({week, Unixtime}).
%% 测试结论为效率下降较多，时间消耗提升47%。影响不小。
%% 不过鉴于计算周的接口调用应该不是非常频繁，在可接受范围内。
% test_utime:test_unix_week(10000, 1000).
% "utime new" [total: 6620(6622)ms avg: 662.000(662.200)us]
% "utime old" [total: 4510(4510)ms avg: 451.000(451.000)us]
% ========================================================================
%            utime new =   6620.00ms [  100.00%]   6622.00ms [  100.00%]
%            utime old =   4510.00ms [   68.13%]   4510.00ms [   68.11%]
% ========================================================================
test_unix_week(Times, DataN) ->
    FunTime = fun() ->
            Secs = urand:rand(1000, 100000),
            utime:unixtime() + Secs
    end,
    N = fix_data_n(DataN),
    TimeList = [ FunTime() || _<-lists:seq(1, N)],
    ptester:run(Times, [
            {"utime new", fun(_) -> each(fun(T) -> utime:unixtime({week, T}) end, TimeList) end},
            {"utime old", fun(_) -> each(fun(T) -> utime_old_unixtime({week, T}) end, TimeList) end}
        ]),
    ok.

%% 修正初始数据的样本数量
fix_data_n(DataN) ->
    if
        not is_integer(DataN) -> 100;
        DataN >= 1 andalso DataN =< 1000 -> DataN;
        true -> 100
    end.

each(Fun, [Elem | Rest]) ->
    Fun(Elem),
    each(Fun, Rest);
each(_Fun, []) ->
    ok.

%% =====================================================
%% 旧utime中的测试用到的相关接口
%% =====================================================
%% 指定时间戳对应的周一0点
utime_old_unixtime({week, Unixtime}) ->
    {Date, Time} = utime_old_unixtime_to_localtime(Unixtime),
    DayOfWeek    = calendar:day_of_the_week(Date),
    DaySecs      = calendar:time_to_seconds(Time),
    Today        = Unixtime - DaySecs,
    Today - (DayOfWeek - 1) * 86400;

%% localtime转换为unixtime
% LocalTime = {{Y,M,D},{H,M,S}}
utime_old_unixtime(LocalTime) ->
    UniversalTime = erlang:localtime_to_universaltime(LocalTime),
    Unixtime = erlang:universaltime_to_posixtime(UniversalTime),
    Unixtime.

utime_old_unixtime_to_localtime(UnixTime) ->
    UniversalTime = erlang:posixtime_to_universaltime(UnixTime),
    erlang:universaltime_to_localtime(UniversalTime).
%% =====================================================

