diff --git a/.gitignore b/.gitignore index 751a61d..479aef7 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,8 @@ deps .rebar3 _build/ _checkouts/ +rebar.lock + +# idea +.idea +*.iml \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..940958f --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +erlUtils +===== + +An OTP library + +Build +----- + + $ rebar3 compile diff --git a/include/com_data.hrl b/include/com_data.hrl new file mode 100644 index 0000000..f30cdf3 --- /dev/null +++ b/include/com_data.hrl @@ -0,0 +1,3 @@ +-record(data_fshandle, {handle :: any(), ver :: any(), sessionKey :: any(), imno :: any(), is_use :: any()}). + +-record(data_roster_status, {host_user :: any(), ver = 0 :: any(), status :: any()}). \ No newline at end of file diff --git a/include/com_log.hrl b/include/com_log.hrl new file mode 100644 index 0000000..f5bd16f --- /dev/null +++ b/include/com_log.hrl @@ -0,0 +1,25 @@ +-define(log_opt_module(__MODULE), {module, __MODULE}). +-define(log_opt_level(__Level), {level, __MODULE}). +-define(log_opt_process(__Process), {process, __Process}). +-define(log_opt_output(__Output), {process, __Output}). + +-define(log_init(__OPTIONS), fun() -> + lists:map(fun({Function, Argvs}) -> + com_log:Function(Argvs) + end, __OPTIONS) + end()). +-define(level_debug, 1). +-define(level_info, 2). +-define(level_error, 3). + +-define(LOG_DEBUG(__DATA), ?LAGER_DEBUG("~p", [__DATA])). +-define(LOG_DEBUG(__FMT, __DATA), ?LAGER_DEBUG("common", __FMT, __DATA)). +-define(LOG_DEBUG(__FunModule, __FMT, __DATA), com_log:log_module(__FunModule, ?level_debug, io_lib:format("[DEBUG] S(~p) M(~p) L(~p)~n" ++ __FMT ++ "~n", [self(), ?MODULE, ?LINE] ++ __DATA))). + +-define(LOG_INFO(__DATA), ?LOG_INFO("~p", [__DATA])). +-define(LOG_INFO(__FMT, __DATA), ?LOG_INFO("common", __FMT, __DATA)). +-define(LOG_INFO(__FunModule, __FMT, __DATA), com_log:log_module(__FunModule, ?level_info, io_lib:format("[INFO] S(~p) M(~p) L(~p)~n" ++ __FMT ++ "~n", [self(), ?MODULE, ?LINE] ++ __DATA))). + +-define(LOG_ERROR(__DATA), ?LOG_ERROR("~p", [__DATA])). +-define(LOG_ERROR(__FMT, __DATA), ?LOG_ERROR("common", __FMT, __DATA)). +-define(LOG_ERROR(__FunModule, __FMT, __DATA), com_log:log_module(__FunModule, ?level_error, io_lib:format("[ERROR] S(~p) M(~p) L(~p)~n" ++ __FMT ++ "~n", [self(), ?MODULE, ?LINE] ++ __DATA))). diff --git a/include/com_time.hrl b/include/com_time.hrl new file mode 100644 index 0000000..b56d289 --- /dev/null +++ b/include/com_time.hrl @@ -0,0 +1,5 @@ +-define(SECONDS_1_HOUR, 3600). %%一时的秒数 +-define(SECONDS_1_DAY, 86400). %%一天的时间(秒) +-define(SECONDS_1_WEEK, 604800). %%一周的时间(秒) +-define(SECONDS_60_MINIUTES, 3600). %%60分钟的秒数 +-define(DIFF_SECONDS_0000_1900, 62167219200). \ No newline at end of file diff --git a/include/meta.hrl b/include/meta.hrl new file mode 100644 index 0000000..077eaa8 --- /dev/null +++ b/include/meta.hrl @@ -0,0 +1,28 @@ +-ifndef(__META__HRL__). +-define(__META__HRL__, true). +-define(parse_transform(__MODULE), -compile({parse_transform, __MODULE})). + +-record(attribute, {line :: integer(), name :: atom(), value :: any()}). + +-record(function, {line :: integer(), name :: any(), args_count :: any(), clauses :: any()}). + +-record(clause, {line :: integer(), args :: any(), guard :: any(), body :: any()}). + +-record(tuple, {line :: integer(), elements :: any()}). + +-record(atom, {line :: integer(), value :: any()}). + +-record(var, {line :: integer(), value :: any()}). + +-record(integer, {line :: integer(), value :: any()}). + +-record(meta_mod, {module :: atom(), + file :: list(), + includes = [] :: list(), + exports = [] :: list(), + records = [] :: list(), + attributes = [] :: list(), + forms = [] :: list(), + eof = {eof, 999} :: {eof, integer()}, + export_all = false :: boolean()}). +-endif. \ No newline at end of file diff --git a/include/module_class.hrl b/include/module_class.hrl new file mode 100644 index 0000000..943789f --- /dev/null +++ b/include/module_class.hrl @@ -0,0 +1,2 @@ +-compile({parse_transform, module_class}). +-include("module_class_def.hrl"). \ No newline at end of file diff --git a/include/module_class_def.hrl b/include/module_class_def.hrl new file mode 100644 index 0000000..dff3163 --- /dev/null +++ b/include/module_class_def.hrl @@ -0,0 +1,10 @@ +-define(TYPE, class_attribute). +-define(QUALIFIER(__QUALIFIER), -?TYPE(__QUALIFIER)). +-define(PRIVATE, private). +-define(PROTECTED, protected). +-define(PUBLIC, public). +-define(FINAL, final). +-define(RELOAD, reload). +-define(ABSTRACT, abstract). +-define(EXTENDS(__CLASS), {extends, __CLASS}). +-define(OVERRIDE, override). \ No newline at end of file diff --git a/include/utComMisc.hrl b/include/utComMisc.hrl new file mode 100644 index 0000000..2ea74c1 --- /dev/null +++ b/include/utComMisc.hrl @@ -0,0 +1,188 @@ + +%% 常用atom定为macro +-define(TRUE, true). +-define(FALSE, false). +-define(BREAK, break). +-define(BREAK(Value), {?BREAK, Value}). +-define(CONTINUE, continue). +-define(CONTINUE(Value), {?CONTINUE, Value}). +-define(UNDEFINED, undefined). + +%% 三目元算符 +-define(ITE(Cond, Then, That), case Cond of true -> Then; _ -> That end). + +%%汉字unicode编码范围 0x4e00 - 0x9fa5 +-define(UNICODE_CHINESE_BEGIN, (4 * 16 * 16 * 16 + 14 * 16 * 16)). +-define(UNICODE_CHINESE_END, (9 * 16 * 16 * 16 + 15 * 16 * 16 + 10 * 16 + 5)). + +-compile({parse_transform, module_strengthen}). + + + +-define(ifdo(__CONDS, __DO), ?func(case __CONDS of ?true -> __DO;_ -> false end)()). +-define(ifdo_else(__CONDS, __DO, _ELSE), ?func(case __CONDS of ?true -> __DO;_ -> _ELSE end)()). +-define(inline(__FUN, __ARGCOUNT), -compile({inline, [__FUN / __ARGCOUNT]})). + +-define(format(__FORMAT, __DATA), io_lib:format(__FORMAT, __DATA)). + +%% format_record(record名, record数据) -> [{#record.field, record_field_value}] +-define(format_record(__RECORD_NAME, __RECORD_DATA), + fun() -> + __Fields = record_info(fields, __RECORD_NAME), + [_ | __DATA] = tuple_to_list(__RECORD_DATA), + {__RECORD_NAME, lists:zip(__Fields, __DATA)} + end()). + +-define(block(__BLOCK), begin __BLOCK end). + +-define(CONFIG(__KEY), ?CONFIG(__KEY, undefined)). + +-define(CONFIG(__KEY, __DEF), (fun() -> + case application:get_env(__KEY) of + {ok, Val} -> Val; + _ -> __DEF + end + end)()). + +-define(CONFIG(__KEY, __SUBKEY, __DEF), (fun() -> + case application:get_env(__KEY) of + {ok, Val} when is_list(Val) -> + proplists:get_value(__SUBKEY, Val, __DEF); + _ -> __DEF + end + end)()). + +-define(LOG_DEBUG(__DATA), ?LOG_DEBUG("~p", [__DATA])). +-define(LOG_DEBUG(__FMT, __DATA), io:format("[DEBUG] S(~p) M(~p) L(~p)~n" ++ __FMT ++ "~n", [self(), ?MODULE, ?LINE] ++ __DATA)). + +-define(LOG_ERROR(__DATA), ?LOG_ERROR("~p", [__DATA])). +-define(LOG_ERROR(__FMT, __DATA), io:format("[ERROR] S(~p) M(~p) L(~p)~n" ++ __FMT ++ "~n", [self(), ?MODULE, ?LINE] ++ __DATA)). + +-define(LOG_INFO(__DATA), ?LOG_INFO("~p", [__DATA])). +-define(LOG_INFO(__FMT, __DATA), io:format("[INFO] S(~p) M(~p) L(~p)~n" ++ __FMT ++ "~n", [com_type:to_list(self()), + com_type:to_list(?MODULE), + com_type:to_list(?LINE)] ++ __DATA)). + +-define(LAGER_DEBUG(__DATA), ?LAGER_DEBUG("~p", [__DATA])). + +-define(LAGER_DEBUG(__FORMAT, __DATA), ?LARGER_LOG(debug, __FORMAT, __DATA)). + +-define(LAGER_INFO(__DATA), ?LARGER_LOG(info, "~p", [__DATA])). + +-define(LAGER_INFO(__FORMAT, __DATA), ?LARGER_LOG(info, __FORMAT, __DATA)). + + +-define(LAGER_WARNING(__DATA), ?LARGER_LOG(warning, "~p", [__DATA])). + +-define(LAGER_WARNING(__FORMAT, __DATA), ?LARGER_LOG(warning, __FORMAT, __DATA)). + +-define(LAGER_ERROR(__DATA), ?LARGER_LOG(error, "~p", [__DATA])). + +-define(LAGER_ERROR(__FORMAT, __DATA), ?LARGER_LOG(error, __FORMAT, __DATA)). + + + + +-define(LARGER_LOG(__LEVEL, __FORMAT, __DATA), lager:log(__LEVEL, self(), "M(~p)L(~p)S(~p) ~n" ++ __FORMAT, [?MODULE, ?LINE, self()] ++ __DATA)). + +-define(debug_kv(__K_V_LIST), lists:foldl(fun({K, V}, Str) -> ?format("~s ~p(~p)", [Str, K, V]) end, "", __K_V_LIST)). + +-define(return(__RETURN), throw(__RETURN)). + +-define(exit(__EXIT), {'EXIT', __EXIT}). +-define(exit(__BASE, __REASON), ?exit({__BASE, __REASON})). + +-define(tmlm(__TAG, __MODULE, __LINE, __MSG), {__TAG, {__MODULE, __LINE}, __MSG}). + +-define(err(__ERR), ?err_match(?MODULE, ?LINE, __ERR)). +-define(err_match(__ERR), ?err_match(_, _, __ERR)). +-define(err_match(__MODULE, __LINE, __ERR), ?tmlm(err, __MODULE, __LINE, __ERR)). + +-define(ok(__OK), ?ok_match(?MODULE, ?LINE, __OK)). +-define(ok_match(__OK), ?ok_match(_, _, __OK)). +-define(ok_match(__MODULE, __LINE, __OK), ?tmlm(ok, __MODULE, __LINE, __OK)). + +-define(notknow(__NOTKNOW), ?notknow_match(?MODULE, ?LINE, __NOTKNOW)). +-define(notknow_match(__NOTKNOW), ?notknow_match(_, _, __NOTKNOW)). +-define(notknow_match(__MODULE, __LINE, __NOTKNOW), ?tmlm(notknow, __MODULE, __LINE, __NOTKNOW)). + +-define(pack_sendbinary(__Binary), {?MODULE, ?LINE, __Binary}). + +-define(noreply(__State), {noreply, __State}). +-define(stop(__Reason, __NewState), {stop, __Reason, __NewState}). + +-define(self, self()). + +-define(msg(__MSG), {msg, ?MODULE, ?LINE, __MSG}). + +-define(send_msg(__MSG), ?send_msg(?self, __MSG)). +-define(send_msg(__SENDER, __MSG), (__SENDER ! __MSG)). + +-define(func(__Fun), fun() -> __Fun end). + +-define(get_value(__KEY, __LIST), ?get_value(__KEY, __LIST, ?undefined)). +-define(get_value(__KEY, __LIST, __DEFAULT), common:get_value(__KEY, __LIST, __DEFAULT)). + +%% base +-define(amc(__MFA, __Options, Module, Line), fun() -> + case catch __MFA of + ?exit(Way, _) -> + ErrMsg = ?get_value(Way, __Options, {Way, undefined}), + Debug = ?get_value(debug, __Options, not_defined), + ?LAGER_ERROR("M(~p)L(~p) D(~p) ErrMsg(~p) stacktrace(~p)", [Module, Line, Debug, ErrMsg, erlang:get_stacktrace()]), + error({undef, __MFA}); + Ret -> Ret + end + end()). + +%% api +-define(amc(__MFA), ?amc(__MFA, [], ?MODULE, ?LINE)). +%% api +-define(amc(__MFA, __Options), ?amc(__MFA, __Options, ?MODULE, ?LINE)). + +-define(catch_exp(__EXP), fun() -> catch __EXP end()). + +-define(SYSTE_PROCESS(__TRUE_OR_FLASE), erlang:process_flag(trap_exit, __TRUE_OR_FLASE)). + +-record(boot, {module :: atom(), type :: boot_type(), hasname = true :: boolean(), params :: any()}). + +-define(boot_type_supervisor, supervisor). +-define(boot_type_worker, worker). +-define(boot_type_simple_worker, simple_worker). +-type boot_type() :: ?boot_type_simple_worker | ?boot_type_supervisor | ?boot_type_worker. +-define(MATH_INT32_MAX, 4294967296). + + +-define(cast_int(__Val), com_type:to_integer(__Val)). +-define(cast_str(__Val), com_type:to_list(__Val)). +-define(cast_erl(__Val), com_type:to_list(__Val)). + +-define(record_key_val_get(__RECORDNAME, __RECORDDATA, __KEY), (fun() -> + case erlang:is_integer(__KEY) of + true -> + erlang:element(__KEY, __RECORDDATA); + false -> + Fields = record_info(fields, __RECORDNAME), + case com_lists:position(__KEY, Fields) of + {error, Error} -> + {error, Error}; + Position -> + erlang:element(Position + 1, __RECORDDATA) + end + end + end)()). + +-define(record_key_val_set(__RECORDNAME, __RECORDDATA, __KEY, __VAL), (fun() -> + case erlang:is_integer(__KEY) of + true -> + erlang:setelement(__KEY, __RECORDDATA, __VAL); + false -> + Fields = record_info(fields, __RECORDNAME), + case com_lists:position(__KEY, Fields) of + {error, Error} -> + {error, Error}; + Position -> + erlang:setelement(Position + 1, __RECORDDATA, __VAL) + end + end + end)()). \ No newline at end of file diff --git a/include/utParseStack.hrl b/include/utParseStack.hrl new file mode 100644 index 0000000..7003170 --- /dev/null +++ b/include/utParseStack.hrl @@ -0,0 +1,20 @@ +-ifdef(OTP_RELEASE). %% this implies 21 or higher +-define(EXCEPTION(Class, Reason, Stacktrace), Class:Reason:Stacktrace). +-define(GET_STACK(Stacktrace), Stacktrace). +-else. +-define(EXCEPTION(Class, Reason, _), Class:Reason). +-define(GET_STACK(_), erlang:get_stacktrace()). +-endif. + +%% 追溯打印函数调用流程 +-define(PRINT_STACK(Tag), + Stack = + try + throw(0) + catch + ?EXCEPTION(_Class, _Reason, Stacktrace) -> + ?GET_STACK(Stacktrace) + end, + io:format("tarce tag:~p cur Stacktrace:", [Tag]), + io:format(utParseStack:parseStack(Stack)) +). \ No newline at end of file diff --git a/include/utTime.hrl b/include/utTime.hrl new file mode 100644 index 0000000..eefe207 --- /dev/null +++ b/include/utTime.hrl @@ -0,0 +1,7 @@ +-define(SECS_MIN, 60). %%一分钟的秒数 +-define(SECS_HOUR, 3600). %%一小时的秒数 +-define(SECS_DAY, 86400). %%一天的时间(秒) +-define(SECS_WEEK, 604800). %%一周的时间(秒) +-define(DAYS_NO_LEAP_YEAR, 365). %% 平年天数 +-define(DAYS_LEAP_YEAR, 366). %% 闰年天数 +-define(SECS_1970, 62167219200). %%utc 1970年经历过的秒数 \ No newline at end of file diff --git a/rebar.config b/rebar.config new file mode 100644 index 0000000..f618f3e --- /dev/null +++ b/rebar.config @@ -0,0 +1,2 @@ +{erl_opts, [debug_info]}. +{deps, []}. \ No newline at end of file diff --git a/src/dataType/utHex.erl b/src/dataType/utHex.erl new file mode 100644 index 0000000..06a0050 --- /dev/null +++ b/src/dataType/utHex.erl @@ -0,0 +1,123 @@ +-module(utHex). + +-compile([export_all, nowarn_export_all]). + +-define(Hex(X), (getHex(X)):16). + +-spec binaryToHex(Bin :: binary()) -> string(). +binaryToHex(Bin) -> + HexBin = <<<> || <> <= Bin>>, + erlang:binary_to_list(HexBin). + +-spec binaryToHexBin(Bin :: binary()) -> binary(). +binaryToHexBin(Bin) -> + <<<> || <> <= Bin>>. + +-spec hexToString(Hex :: string()) -> string(). +hexToString(Hex) -> + {String, _} = + lists:foldr( + fun(E, {Acc, nolow}) -> + {Acc, deHex(E)}; + (E, {Acc, LO}) -> + {[deHex(E) * 16 + LO | Acc], nolow} + end, + {[], nolow}, Hex), + String. + +-spec hexToBinary(Hex :: string()) -> string(). +hexToBinary(Hex) -> + HexBin = list_to_binary(Hex), + <<<<(deHex(X1) * 16 + deHex(X2))>> || <> <= HexBin>>. + +-spec hexBinToString(HexBin :: binary()) -> string(). +hexBinToString(HexBin) -> + [(deHex(X1) * 16 + deHex(X2)) || <> <= HexBin]. + +-spec hexBinToBinary(HexBin :: binary()) -> string(). +hexBinToBinary(HexBin) -> + <<<<(deHex(X1) * 16 + deHex(X2))>> || <> <= HexBin>>. + +-spec integerToHex(I :: integer()) -> string(). +integerToHex(I) -> + erlang:integer_to_list(I, 16). + +-spec hexToInteger(Hex :: string()) -> integer(). +hexToInteger(Hex) -> + lists:foldl(fun(E, Acc) -> Acc * 16 + deHex(E) end, 0, Hex). + +-spec rawBinaryToInteger(Bin :: binary()) -> integer(). +rawBinaryToInteger(Bin) -> + rawBinaryToInteger(Bin, 0). + +-spec rawBinaryToInteger(Bin :: binary(), Acc :: integer()) -> integer(). +rawBinaryToInteger(<<>>, Acc) -> + Acc; +rawBinaryToInteger(<>, Acc) -> + rawBinaryToInteger(Rest, Acc * 256 + X). + +-spec integerToRawBinary(I :: integer()) -> binary(). +integerToRawBinary(I) -> + integerToRawBinary(I, 16, []). + +-spec integerToRawBinary(I :: integer(), Len :: pos_integer()) -> binary(). +integerToRawBinary(I, Len) -> + integerToRawBinary(I, Len, []). + +integerToRawBinary(I, Len, Acc) when I < 256 -> + NewAcc = [I | Acc], + ZeroPadding = lists:duplicate(Len - length(NewAcc), 0), + NewAcc2 = [ZeroPadding | NewAcc], + list_to_binary(NewAcc2); +integerToRawBinary(I, Len, Acc) -> + Div = I div 256, + Rem = I rem 256, + integerToRawBinary(Div, Len, [Rem | Acc]). + +deHex(H) when H >= $a, H =< $f -> H - $a + 10; +deHex(H) when H >= $A, H =< $F -> H - $A + 10; +deHex(H) when H >= $0, H =< $9 -> H - $0. + +-compile({inline, [getHex/1]}). +-spec getHex(X :: non_neg_integer()) -> integer(). +getHex(X) -> + element(X + 1, + { + 16#3030, 16#3031, 16#3032, 16#3033, 16#3034, 16#3035, 16#3036, + 16#3037, 16#3038, 16#3039, 16#3061, 16#3062, 16#3063, 16#3064, + 16#3065, 16#3066, 16#3130, 16#3131, 16#3132, 16#3133, 16#3134, + 16#3135, 16#3136, 16#3137, 16#3138, 16#3139, 16#3161, 16#3162, + 16#3163, 16#3164, 16#3165, 16#3166, 16#3230, 16#3231, 16#3232, + 16#3233, 16#3234, 16#3235, 16#3236, 16#3237, 16#3238, 16#3239, + 16#3261, 16#3262, 16#3263, 16#3264, 16#3265, 16#3266, 16#3330, + 16#3331, 16#3332, 16#3333, 16#3334, 16#3335, 16#3336, 16#3337, + 16#3338, 16#3339, 16#3361, 16#3362, 16#3363, 16#3364, 16#3365, + 16#3366, 16#3430, 16#3431, 16#3432, 16#3433, 16#3434, 16#3435, + 16#3436, 16#3437, 16#3438, 16#3439, 16#3461, 16#3462, 16#3463, + 16#3464, 16#3465, 16#3466, 16#3530, 16#3531, 16#3532, 16#3533, + 16#3534, 16#3535, 16#3536, 16#3537, 16#3538, 16#3539, 16#3561, + 16#3562, 16#3563, 16#3564, 16#3565, 16#3566, 16#3630, 16#3631, + 16#3632, 16#3633, 16#3634, 16#3635, 16#3636, 16#3637, 16#3638, + 16#3639, 16#3661, 16#3662, 16#3663, 16#3664, 16#3665, 16#3666, + 16#3730, 16#3731, 16#3732, 16#3733, 16#3734, 16#3735, 16#3736, + 16#3737, 16#3738, 16#3739, 16#3761, 16#3762, 16#3763, 16#3764, + 16#3765, 16#3766, 16#3830, 16#3831, 16#3832, 16#3833, 16#3834, + 16#3835, 16#3836, 16#3837, 16#3838, 16#3839, 16#3861, 16#3862, + 16#3863, 16#3864, 16#3865, 16#3866, 16#3930, 16#3931, 16#3932, + 16#3933, 16#3934, 16#3935, 16#3936, 16#3937, 16#3938, 16#3939, + 16#3961, 16#3962, 16#3963, 16#3964, 16#3965, 16#3966, 16#6130, + 16#6131, 16#6132, 16#6133, 16#6134, 16#6135, 16#6136, 16#6137, + 16#6138, 16#6139, 16#6161, 16#6162, 16#6163, 16#6164, 16#6165, + 16#6166, 16#6230, 16#6231, 16#6232, 16#6233, 16#6234, 16#6235, + 16#6236, 16#6237, 16#6238, 16#6239, 16#6261, 16#6262, 16#6263, + 16#6264, 16#6265, 16#6266, 16#6330, 16#6331, 16#6332, 16#6333, + 16#6334, 16#6335, 16#6336, 16#6337, 16#6338, 16#6339, 16#6361, + 16#6362, 16#6363, 16#6364, 16#6365, 16#6366, 16#6430, 16#6431, + 16#6432, 16#6433, 16#6434, 16#6435, 16#6436, 16#6437, 16#6438, + 16#6439, 16#6461, 16#6462, 16#6463, 16#6464, 16#6465, 16#6466, + 16#6530, 16#6531, 16#6532, 16#6533, 16#6534, 16#6535, 16#6536, + 16#6537, 16#6538, 16#6539, 16#6561, 16#6562, 16#6563, 16#6564, + 16#6565, 16#6566, 16#6630, 16#6631, 16#6632, 16#6633, 16#6634, + 16#6635, 16#6636, 16#6637, 16#6638, 16#6639, 16#6661, 16#6662, + 16#6663, 16#6664, 16#6665, 16#6666 + }). diff --git a/src/dataType/utTypeCast.erl b/src/dataType/utTypeCast.erl new file mode 100644 index 0000000..c4eadd2 --- /dev/null +++ b/src/dataType/utTypeCast.erl @@ -0,0 +1,112 @@ +-module(utTypeCast). + +-compile([export_all, nowarn_export_all]). + +toFloat(Value) when is_list(Value) -> list_to_float(Value); +toFloat(Value) when is_binary(Value) -> binary_to_float(Value); +toFloat(Value) when is_integer(Value) -> erlang:float(Value); +toFloat(Value) when is_float(Value) -> Value. + +toList(undefined) -> "undefined"; +toList(null) -> "null"; +toList(Value) when is_tuple(Value) -> tuple_to_list(Value); +toList(Value) when is_binary(Value) -> binary_to_list(Value); +toList(Value) when is_bitstring(Value) -> bitstring_to_list(Value); +toList(Value) when is_integer(Value) -> integer_to_list(Value); +toList(Value) when is_float(Value) -> float_to_list(Value, [{decimals, 6}, compact]); +toList(Value) when is_atom(Value) -> atom_to_list(Value); +toList(Value) when is_list(Value) -> Value; +toList([Tuple | PropList] = Value) when is_list(PropList) and is_tuple(Tuple) -> + lists:map(fun({K, V}) -> {toList(K), toList(V)} end, [Value]). + +%% to_list(Term) when is_binary(Term) -> +%% case unicode:characters_to_binary(Term, utf8, utf8) of +%% Term -> +%% unicode:characters_to_list(Term); +%% _ -> +%% binary_to_list(Term) +%% end. + +toBinary(Value) when is_integer(Value) -> integer_to_binary(Value); +toBinary(Value) when is_list(Value) -> list_to_binary(Value); +toBinary(Value) when is_float(Value) -> float_to_binary(Value, [{decimals, 6}, compact]); +toBinary(Value) when is_atom(Value) -> atom_to_binary(Value, utf8); +toBinary(Value) when is_binary(Value) -> Value; +toBinary([Tuple | PropList] = Value) when is_list(PropList) and is_tuple(Tuple) -> + lists:map(fun({K, V}) -> {toBinary(K), toBinary(V)} end, Value); +toBinary(Value) -> term_to_binary(Value). + +toInteger(undefined) -> undefined; +toInteger(Value) when is_float(Value) -> trunc(Value); +toInteger(Value) when is_list(Value) -> list_to_integer(Value); +toInteger(Value) when is_binary(Value) -> binary_to_integer(Value); +toInteger(Value) when is_tuple(Value) -> toInteger(tuple_to_list(Value)); +toInteger(Value) when is_integer(Value) -> Value. + + +dataType(Data) when is_list(Data) -> list; +dataType(Data) when is_integer(Data) -> integer; +dataType(Data) when is_binary(Data) -> binary; +dataType(Data) when is_function(Data) -> function; +dataType(Data) when is_tuple(Data) -> tuple; +dataType(Data) when is_atom(Data) -> atom; +dataType(Data) when is_bitstring(Data) -> bitstring; +dataType(Data) when is_boolean(Data) -> boolean; +dataType(Data) when is_float(Data) -> float; +dataType(Data) when is_number(Data) -> number; +dataType(Data) when is_pid(Data) -> pid; +dataType(Data) when is_port(Data) -> port; +dataType(_Data) -> not_know. + +%% Trim the binary +-spec trim(Bin :: binary()) -> binary(). +trim(Bin) when is_binary(Bin) -> trimHead(trimTail(Bin)). + +%% Trim head of binary +-spec trimHead(Bin :: binary()) -> binary(). +trimHead(<<>>) -> <<>>; +trimHead(<> = Bin) -> + case is_whitespace(C) of + true -> trimHead(BinTail); + false -> Bin + end. + +%% Trim tail of binary +-spec trimTail(Bin :: binary()) -> binary(). +trimTail(<<>>) -> <<>>; +trimTail(Bin) -> + Size = byte_size(Bin) - 1, + <> = Bin, + case is_whitespace(C) of + true -> trimTail(BinHead); + false -> Bin + end. + +%% Check if the char is a whitespace +-spec is_whitespace(char()) -> true | false. +is_whitespace($\s) -> true; +is_whitespace($\t) -> true; +is_whitespace($\n) -> true; +is_whitespace($\r) -> true; +is_whitespace(_) -> false. + +%% term序列化, term转为string +term_to_string(Bin) when is_binary(Bin) -> + binary_to_list(Bin); +term_to_string(Term) -> + case catch io_lib:format("~w", [Term]) of + {'EXIT', _} -> lists:flatten(io_lib:format("~p", [Term])); + GoodString -> lists:flatten(GoodString) + end. + +%% term反序列化, string转换为term +string_to_term(String) -> + case erl_scan:string(String ++ ".") of + {ok, Tokens, _} -> + case erl_parse:parse_term(Tokens) of + {ok, Term} -> Term; + _Err -> String + end; + _Error -> + undefined + end. \ No newline at end of file diff --git a/src/erlUtils.app.src b/src/erlUtils.app.src new file mode 100644 index 0000000..e4694f2 --- /dev/null +++ b/src/erlUtils.app.src @@ -0,0 +1,14 @@ +{application, erlUtils, + [{description, "An OTP library"}, + {vsn, "0.1.0"}, + {registered, []}, + {applications, + [kernel, + stdlib + ]}, + {env,[]}, + {modules, []}, + + {licenses, ["Apache 2.0"]}, + {links, []} + ]}. diff --git a/src/erlUtils.erl b/src/erlUtils.erl new file mode 100644 index 0000000..4106bf7 --- /dev/null +++ b/src/erlUtils.erl @@ -0,0 +1,3 @@ +-module(erlUtils). + +-export([]). diff --git a/src/stackStrace/utParseStack.erl b/src/stackStrace/utParseStack.erl new file mode 100644 index 0000000..49a016f --- /dev/null +++ b/src/stackStrace/utParseStack.erl @@ -0,0 +1,82 @@ +-module(utParseStack). +-include("utParseStack.hrl"). + +-compile([export_all, nowarn_export_all]). + +%% 堆栈回溯(stacktrace)是{Module,Function,Arity,Location}元组的列表。 +%% Arity: 根据异常,Arity字段可以是该函数调用的参数列表,而不是arity整数。 +%% Location: 是一个二元组的列表(可能为空),可以指示该函数在源代码中的位置。 +%% 第一个元素是描述第二个元素中信息类型的原子。可能发生以下情况: +%% [{file, 一个字符串, 代表函数源文件的文件名}, {line, 元组的第二个元素是发生异常或调用函数的源文件中的行号, 整数> 0} : + +%% term序列化, term转为string +term_to_string(Bin) when is_binary(Bin) -> + binary_to_list(Bin); +term_to_string(Term) -> + case catch io_lib:format("~w", [Term]) of + {'EXIT', _} -> lists:flatten(io_lib:format("~p", [Term])); + GoodString -> lists:flatten(GoodString) + end. + +%% term反序列化, string转换为term +string_to_term(String) -> + case erl_scan:string(String ++ ".") of + {ok, Tokens, _} -> + case erl_parse:parse_term(Tokens) of + {ok, Term} -> Term; + _Err -> String + end; + _Error -> + undefined + end. + +parseStack(Stacktrace, Class, Reason) -> + CR = io_lib:format("~n Class:~s~n Reason:~p~n Stacktrace:", [Class, Reason]), + [CR | parseStack(Stacktrace)]. + +parseStack(Stacktrace) -> + [begin + case Location of + [] -> + [<<"\n ">>, atom_to_list(Mod), <<":">>, atom_to_list(Func), <<"(">>, term_to_string(Arity), <<")">>]; + [{file, File}, {line, Line}] -> + [<<"\n ">>, atom_to_list(Mod), <<":">>, atom_to_list(Func), <<"/">>, integer_to_binary(Arity), <<" (">>, File, <<":">>, integer_to_binary(Line), <<")">>]; + _ -> + [<<"\n ">>, atom_to_list(Mod), <<":">>, atom_to_list(Func), <<" (">>, term_to_string(Arity), <<")">>, term_to_string(Location)] + end + end || {Mod, Func, Arity, Location} <- Stacktrace + ]. + +printStack(Tag) -> + ?PRINT_STACK(Tag). + +%% 下面是测试代码 +make_throw() -> + throw({test, exception}). + +bad_arity() -> + lists:concat([], []). + +bad_arg(ErrArgs) -> + integer_to_list(ErrArgs). + +test11(Index) -> + application:set_env(lager, reverse_pretty_stacktrace, false), + try + case Index of + 1 -> + make_throw(); + 2 -> + bad_arity(); + 3 -> + bad_arg(Index + 0.0) + end + catch + ?EXCEPTION(Class, Reason, Stacktrace) -> + Stacktrace = ?GET_STACK(Stacktrace), + io:format(parseStack(Stacktrace)), + io:format(parseStack(Stacktrace, Class, Reason)) + %% lagere使用示例 + %% lager:error(parse_stack(Stacktrace)), + %% lager:error(parse_stack(Stacktrace, Class, Reason)) + end. \ No newline at end of file diff --git a/src/startStop/utAppStart.erl b/src/startStop/utAppStart.erl new file mode 100644 index 0000000..71e8839 --- /dev/null +++ b/src/startStop/utAppStart.erl @@ -0,0 +1,264 @@ +-module(utAppStart). + +-export([ + startApp/2 +]). + +-export([ + ensure_started/1, + ensure_loaded/1, + stop_apps/1, + reload/1, + reload_modules/1, + get_var/3, + get_var/2, + set_var/3, + load_config/1, + load_config/2, + load_config/3 +]). + + +startApp(App, Type) -> + startRely(application:start(App, Type), App, Type). + +startRely(ok, _App, _Type) -> + ok; +startRely({error, {already_started, _App}}, _App, _Type) -> + ok; +startRely({error, {not_started, Rely}}, App, Type) -> + ok = start(Rely, Type), + start(App, Type); +startRely({error, Reason}, App, Type) -> + erlang:error({app_start_failed, App, Type, Reason}). + +start(_Rely, _Type) -> + ok. + +%% @doc +%% Tries to start applications or check whether they have started. +%% @end +-spec ensure_started(list(atom()) | atom()) -> ok | error. +ensure_started([]) -> ok; + +ensure_started(App) when is_atom(App) -> ensure_started([App]); + +ensure_started([App | Apps]) -> + case application:start(App) of + ok -> ensure_started(Apps); + {error, {already_started, App}} -> ensure_started(Apps); + {error, {not_started, Dep}} -> ensure_started(Dep), ensure_started([App | Apps]) + end. + + +%% @doc +%% Tries to load modules. +%% @end +-spec ensure_loaded(list(atom()) | atom()) -> ok | error. +ensure_loaded([]) -> ok; + +ensure_loaded(Mod) when is_atom(Mod) -> ensure_started([Mod]); + +ensure_loaded([Mod | Mods]) -> + {module, _} = code:ensure_loaded(Mod), + ensure_loaded(Mods). + +%% @doc +%% Stop applications. +%% @end +-spec stop_apps(list(atom())|atom()) -> ok. +stop_apps([]) -> ok; +stop_apps(App) when is_atom(App) -> stop_apps([App]); +stop_apps([App | Apps]) -> + application:stop(App), + stop_apps(Apps). + + +%% @doc Compiles and reloads application modules +%% @end +-spec reload(atom()) -> ok. +reload(App) -> + application:load(App), + case application:get_key(App, modules) of + undefined -> + ok; + {ok, Modules} -> + reload_modules(lists:usort(Modules)) + end. + + +%% @doc Reload specified modules +%% @end +-spec reload_modules(list(atom()) | atom()) -> ok. +reload_modules([]) -> ok; + +reload_modules([?MODULE | T]) -> reload_modules(T); + +reload_modules(M) when is_atom(M) -> reload_modules([M]); + +reload_modules([H | T]) -> + reload_mod(H), + reload_modules(T). + +%% @private +-spec reload_mod(atom()) -> true. +reload_mod(Module) when is_atom(Module) -> + error_logger:info_msg("[ulitos] Reload module: ~p", [Module]), + code:purge(Module), + code:load_file(Module), + true. + + +%% @doc +%% Return application environment variable called Var if exists; otherwise return Def. +%% @end +-spec get_var(atom(), atom(), any()) -> any(). +get_var(App, Var, Def) -> + case application:get_env(App, Var) of + {ok, Val} -> Val; + _ -> Def + end. + + +-spec get_var(atom(), atom()) -> any() | undefined. +get_var(App, Var) -> + get_var(App, Var, undefined). + + +%% @doc +%% Set application environment variable. +%% @end +-spec set_var(atom(), atom(), any()) -> ok. +set_var(App, Var, Val) -> + application:set_env(App, Var, Val). + +%% @doc +%% Set application App environment from default config ("priv/APP_NAME.config"). +%% @end +-spec load_config(atom()) -> ok. +load_config(App) -> + File = atom_to_list(App) ++ ".config", + load_config(App, File). + +%% @doc +%% Set application App environment vars from file with name File located in app priv_dir. +%% @end +-spec load_config(atom(), string()) -> ok. +load_config(App, File) -> + load_config(App, File, []). + +%% @doc +%% Set application App environment vars from file with name File located in some of Dirs or in priv_dir. +%% @end +-spec load_config(atom(), string(), list()) -> ok. +load_config(App, File, Dirs) -> + Path = code:priv_dir(App), + Env = load_file_config(Dirs ++ [Path], File), + [application:set_env(App, Key, Value) || {Key, Value} <- Env], + ok. + +%% @private +-spec load_file_config(Paths :: list(string()), File :: string()) -> any(). +load_file_config(Paths, File) -> + case file:path_consult(Paths, File) of + {ok, Env, _Path} -> Env; + _ -> [] + end. + +%% Tests +-ifdef(TEST). +-include_lib("eunit/include/eunit.hrl"). + +-define(PATH(File), filename:join([code:lib_dir(ulitos), File])). + +load_config_test_() -> + {"List dir tests", + {foreach, + fun config_setup/0, + fun config_cleanup/1, + [ + fun load_config_by_app_t_/1, + fun load_config_by_name_t_/1, + fun load_config_by_name_and_paths_t_/1, + fun load_config_by_name_and_paths_2_t_/1 + ] + } + }. + +unconsult(File, L) -> + {ok, S} = file:open(File, write), + lists:foreach(fun(X) -> io:format(S, "~p.~n", [X]) end, L), + file:close(S). + +config_setup() -> + unconsult(?PATH("priv/ulitos.config"), [{test, 1}]), + ok = file:make_dir(?PATH("priv/a")), + unconsult(?PATH("priv/a/ulitos.config"), [{test, 2}]), + unconsult(?PATH("priv/ul.config"), [{test, 3}]), + unconsult(?PATH("priv/a/ul.config"), [{test, 4}]), + ok. + +config_cleanup(_) -> + ulitos_file:recursively_del_dir(?PATH("priv/a")), + file:delete(?PATH("priv/ulitos.config")), + file:delete(?PATH("priv/ul.config")), + application:unset_env(ulitos, test), + ok. + +load_config_by_app_t_(_) -> + load_config(ulitos), + [ + ?_assertEqual(1, get_var(ulitos, test)) + ]. + +load_config_by_name_t_(_) -> + load_config(ulitos, "ul.config"), + [ + ?_assertEqual(3, get_var(ulitos, test)) + ]. + +load_config_by_name_and_paths_t_(_) -> + load_config(ulitos, "ul.config", [?PATH("priv/b"), ?PATH("priv/a")]), + [ + ?_assertEqual(4, get_var(ulitos, test)) + ]. + +load_config_by_name_and_paths_2_t_(_) -> + load_config(ulitos, "ul.config", [?PATH("priv/b"), ?PATH("c")]), + [ + ?_assertEqual(3, get_var(ulitos, test)) + ]. + +reload_modules_test_() -> + {"Reload module code", + {foreach, + fun reload_setup/0, + fun reload_cleanup/1, + [ + fun reload_modules_t_/1 + ] + } + }. + +reload_setup() -> + code:add_patha(?PATH("")), + ok = file:write_file(?PATH("my_module.erl"), <<"-module(my_module).\n-export([say/0]).\nsay() -> hello.">>), + {ok, _} = compile:file(?PATH("my_module.erl"), {outdir, ?PATH("")}), + {module, my_module} = code:load_file(my_module), + ok. + +reload_cleanup(_) -> + ok. + +reload_modules_t_(_) -> + Before = my_module:say(), + ok = file:write_file(?PATH("my_module.erl"), <<"-module(my_module).\n-export([say/0]).\nsay() -> hi.">>), + {ok, _} = compile:file(?PATH("my_module.erl"), {outdir, ?PATH("")}), + reload_modules(my_module), + After = my_module:say(), + [ + ?_assertEqual(hello, Before), + ?_assertEqual(hi, After) + ]. + +-endif. diff --git a/src/startStop/utSrvManager.erl b/src/startStop/utSrvManager.erl new file mode 100644 index 0000000..fb273f5 --- /dev/null +++ b/src/startStop/utSrvManager.erl @@ -0,0 +1 @@ +-module(utSrvManager). \ No newline at end of file diff --git a/src/startStop/utStopSrv1.escript b/src/startStop/utStopSrv1.escript new file mode 100644 index 0000000..abe95ce --- /dev/null +++ b/src/startStop/utStopSrv1.escript @@ -0,0 +1,20 @@ +#!/usr/bin/env escript + +-define(AIM_NODE, 'stopNode@127.0.0.1'). +-define(CUR_NODE, 'stop-source-node@127.0.0.1'). %% 这个参数可以在上面直接设置 +-define(COOKIE, '123'). %% 这个参数可以在上面直接设置 + +main(_Arge) -> + net_kernel:start([?CUR_NODE, longnames]), + erlang:set_cookie(?CUR_NODE, ?COOKIE), + io:format("IMY***************** cuer node info ~p ~p ~n", [node(), erlang:get_cookie()]), + case net_adm:ping(?AIM_NODE) of + pong -> + io:format("the aims server:~p is online~n", [?AIM_NODE]), + io:format("to close it~n"), + rpc:call(?AIM_NODE, init, stop, []), + halt(0); + _ -> + io:format("the aims server:~p is not online~n", [?AIM_NODE]), + halt(1) + end. diff --git a/src/startStop/utStopSrv2.escript b/src/startStop/utStopSrv2.escript new file mode 100644 index 0000000..e9f91da --- /dev/null +++ b/src/startStop/utStopSrv2.escript @@ -0,0 +1,19 @@ +#!/usr/bin/env escript +%% -*- erlang -* +%%! -name stop-source-node@127.0.0.1 -setcookie 123 -hidden + +-define(AIM_NODE, 'stopNode@127.0.0.1'). + +main(_Args) -> + io:format("IMY***************** cuer node info ~p ~p ~n", [node(), erlang:get_cookie()]), + case net_adm:ping(?AIM_NODE) of + pong -> + io:format("the aims server:~p is online~n", [?AIM_NODE]), + io:format("to close it~n"), + timer:sleep(10000), + rpc:call(?AIM_NODE, init, stop, []), + halt(0); + _ -> + io:format("the aims server:~p is online~n", [?AIM_NODE]), + halt(1) + end. diff --git a/src/testCase/utFunCallCase.erl b/src/testCase/utFunCallCase.erl new file mode 100644 index 0000000..e0d981d --- /dev/null +++ b/src/testCase/utFunCallCase.erl @@ -0,0 +1,273 @@ +-module(utFunCallCase). + +-compile([export_all, nowarn_function, nowarn_unused_vars, nowarn_export_all]). + +-record(cycleData, { + module = test + , isEnter = false + , hibernateAfter = infinity + , isHibernate = false + , lastStatus = init_status + , lastState = #{11 => 555, 44 => 434} + , postponed = [1,3,"dffd", "fdf"] + , timers = #{etime => {aaa, fdfd}} +}). + +-record(handler, { + module = test + , id = false + , state = {fd,34, #{1 => 1343}, 32} + , supId = [12,34,45] +}). + +tt1(N) -> + tt1(N, #cycleData{}, [123421,434,34], {12222,343, "fdfd"}, fff, "ArgD"). + +tt1(0, CycleData, ArgA, ArgB, ArgC, ArgD) -> + ok; +tt1(N, #cycleData{lastState = LastState, isEnter = IsEnter, hibernateAfter = HibernateAfter, module = Module} = CycleData, ArgA, ArgB, ArgC, ArgD) -> + _ = is_atom(LastState), + _ = is_atom(IsEnter), + _ = is_atom(HibernateAfter), + _ = is_atom(Module), + tt1(N - 1, CycleData, ArgA, ArgB, ArgC, ArgD). + +tt2(N) -> + tt2(N, #cycleData{}, [123421,434,34], {12222,343, "fdfd"}, fff, "ArgD"). + +tt2(0, _CycleData, _ArgA, _ArgB, _ArgC, _ArgD) -> + ok; +tt2(N, CycleData, ArgA, ArgB, ArgC, ArgD) -> + LastState = element(#cycleData.lastState, CycleData), + IsEnter = element(#cycleData.isEnter, CycleData), + HibernateAfter= element(#cycleData.hibernateAfter, CycleData), + Module = element(#cycleData.module, CycleData), + I1 = is_atom(LastState), + I2 = is_atom(IsEnter), + I3 = is_atom(HibernateAfter), + I4 = is_atom(Module), + _Ret = I1 andalso I2 andalso I3 andalso I4 andalso true, + tt2(N -1, CycleData, ArgA, ArgB, ArgC, ArgD). + +tt3(N) -> + tt3(N, #cycleData{}, [123421,434,34], {12222,343, "fdfd"}, fff, "ArgD"). + +tt3(0, CycleData, ArgA, ArgB, ArgC, ArgD) -> + ok; +tt3(N, CycleData, ArgA, ArgB, ArgC, ArgD) -> + NewCycleData = CycleData#cycleData{module = tttt, lastState = #{11 => 22, 22 => 33}, isEnter = false}, + tt3(N - 1, NewCycleData, ArgA, ArgB, ArgC, ArgD). + +tt4(N) -> + tt4(N, #cycleData{}, [123421,434,34], {12222,343, "fdfd"}, fff, "ArgD"). + +tt4(0, CycleData, ArgA, ArgB, ArgC, ArgD) -> + ok; +tt4(N, CycleData, ArgA, ArgB, ArgC, ArgD) -> + New1 = setelement(#cycleData.module, CycleData, tttt), + New2 = setelement(#cycleData.lastState, New1, #{11 => 22, 22 => 33}), + New3 = setelement(#cycleData.isEnter, New2, false), + tt4(N -1, New3, ArgA, ArgB, ArgC, ArgD). + +tt5(N) -> + tt5(N, #cycleData{}, [123421,434,34]). + +tt5(0, CycleData, AA) -> + ok; +tt5(N, CycleData, AA) -> + tt5(N - 1, CycleData, AA). + +tt6(N) -> + tt6(N,test, false, infinity, false, init_status, #{11 => 555, 44 => 434}, [1,3,"dffd", "fdf"], #{etime => {aaa, fdfd}}, [123421,434,34]). + +tt6(0, A1, B, C, D, E, F, G, H, AA) -> + ok; +tt6(N, A1, B, C, D, E, F, G, H, AA) -> + tt6(N -1, A1, B, C, D, E, F, G, H, AA). + +tt7(0) -> + ok; +tt7(N) -> + tt7(N -1). + + +tt8(N) -> + tt8(N, #cycleData{}). + +tt8(0, CycleData) -> + ok; +tt8(N, #cycleData{module = Module, lastState = Lasst, postponed = Postponed} = AA) -> + A = setelement(#cycleData.module, AA, ttt), + B = setelement(#cycleData.isEnter, A, trye), + %% B = setelement(#cycleData.lastState, A, #{22 => 555, 55 => 434}), + %% C = setelement(#cycleData.postponed, B, [1,3,"fdf", "dffd"]), + tt8(N - 1, B). + +tt88(N) -> + tt88(N, #cycleData{}). + +tt88(0, CycleData) -> + ok; +tt88(N, #cycleData{module = Module, lastState = Lasst, postponed = Postponed} = AA) -> + %%C = setelement(#cycleData.postponed, AA, [1,3,"fdf", "dffd"]), + %%B = setelement(#cycleData.lastState, C, #{22 => 555, 55 => 434}), + B = setelement(#cycleData.isEnter, AA, trye), + A = setelement(#cycleData.module, B, ttt), + tt88(N - 1, A). + +tt888(N) -> + tt888(N, #cycleData{}). + +tt888(0, CycleData) -> + ok; +tt888(N, #cycleData{module = Module, lastState = Lasst, postponed = Postponed} = AA) -> + A = AA#cycleData{postponed = [1,3,"fdf", "dffd"], module = ttt, lastState = #{22 => 555, 55 => 434}}, + tt888(N - 1, A). + +tt9(N) -> + Data = #cycleData{}, + put(a, Data#cycleData.module), + put(b, Data#cycleData.isEnter), + put(c, Data#cycleData.hibernateAfter), + put(d, Data#cycleData.isHibernate), + put(e, Data#cycleData.lastStatus), + put(f, Data#cycleData.lastState), + put(g, Data#cycleData.postponed), + tt10(N). + +tt10(0) -> + ok; +tt10(N) -> + A = get(a), + put(a, ttt), + B = get(f), + put(f, #{22 => 555, 55 => 434}), + C = get(g), + put(g, [1,3,"fdf", "dffd"]), + _Ret = A orelse B orelse C orelse false, + tt10(N -1). + +tt11(N) -> + tt11(N, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 0). + +tt11(0, A, B, C, D, E, F, G, H, I, J, BB) -> + A; +tt11(N, A, B, C, D, E, F, G, H, I, J, BB1) -> + BB = A + B + C + D + E + F + G + H + I + J, + tt11(N -1, A, B, C, D, E, F, G, H, I, J, BB). + +tt12(N) -> + tt12(N, 10,0). + +tt12(0, _A, AA) -> + _A; +tt12(N, A, A1) -> + AA = A + A + A + A + A + A + A + A + A + A, + tt12(N - 1, A, AA). + +tt13(N) -> + put({pd_epm, {test, 1}}, #handler{}), + put({pd_epm, {test, 2}}, #handler{}), + put({pd_epm, {test, 3}}, #handler{}), + put({pd_epm, {test, 4}}, #handler{}), + put({pd_epm, {test, 5}}, #handler{}), + put({pd_epm, {test, 6}}, #handler{}), + put({pd_epm, {test, 7}}, #handler{}), + put({pd_epm, {test, 8}}, #handler{}), + put({pd_epm, {test, 9}}, #handler{}), + put({pd_epm, {test, 10}}, #handler{}), + put(pd_list, [{test, 1},{test, 2},{test, 3},{test, 4},{test, 5},{test, 6},{test, 7},{test, 8},{test, 9},{test, 10}]), + tt133(N, 0), + tt134(N). + +tt133(0, Ret) -> + Ret; +tt133(N, _Ret) -> + Ret = get(pd_list), + tt133(N-1, Ret). + +tt134(0) -> + ok; +tt134(N) -> + A = get({pd_epm, {test, 5}}), + put({pd_epm, {test, 5}}, A#handler{state = [332,34,3,4,3,53,6]}), + tt134(N-1). + +%,#handler{id = {test, 6}},#handler{id = {test, 7}},#handler{id = {test, 8}},#handler{id = {test, 9}},#handler{id = {test, 10}} + +tt14(N) -> + List = [#handler{id = {test, 1}}, #handler{id = {test, 2}},#handler{id = {test, 3}},#handler{id = {test, 4}},#handler{id = {test, 5}}], + tt144(N, List), + tt145(N, List). + + +tt144(0, List) -> + ok; +tt144(N, List) -> + List, + tt144(N-1, List). + +search({Mod, Id}, [Ha|_MSL]) when Ha#handler.module =:= Mod, + Ha#handler.id =:= Id -> + {ok, Ha}; +search(Mod, [Ha|_MSL]) when Ha#handler.module =:= Mod, + not Ha#handler.id -> + {ok, Ha}; +search(Handler, [_|MSL]) -> + search(Handler, MSL); +search(_, []) -> + false. + +replace({Mod, Id}, [Ha|MSL], NewHa) when Ha#handler.module =:= Mod, + Ha#handler.id =:= Id -> + [NewHa|MSL]; +replace(Mod, [Ha|MSL], NewHa) when Ha#handler.module =:= Mod, + not Ha#handler.id -> + [NewHa|MSL]; +replace(Handler, [Ha|MSL], NewHa) -> + [Ha|replace(Handler, MSL, NewHa)]; +replace(_, [], NewHa) -> + [NewHa]. + +tt145(0, List) -> + ok; +tt145(N, List) -> + case lists:keyfind({test,2}, #handler.id, List) of + #handler{} = A -> + NewList = lists:keyreplace({test,3}, #handler.id, List, A#handler{state = [332,34,3,4,3,53,6]}), + tt145(N-1, NewList); + _ -> + tt145(N-1, List) + end. + +tt15(N) -> + D = dict:new(), + D1 = dict:store({test,1}, #handler{id = 1}, D), + tt15(N, D1). + +tt15(0, CycleData) -> + ok; +tt15(N, D1) -> + New = case dict:find({test,2}, D1) of + error -> + dict:store({test,2}, #handler{id = 2}, D1); + {ok, Value} -> + dict:store({test,2}, #handler{id = 2}, D1) + end, + tt15(N - 1, New). + +tt16(N) -> + put({test,1}, #handler{id =1}), + tt166(N). + +tt166(0) -> + ok; +tt166(N) -> + Ret = get({test,2}), + put({test,2}, #handler{id = Ret}), + tt166(N -1). + + + + + diff --git a/src/testCase/utTestBinary.erl b/src/testCase/utTestBinary.erl new file mode 100644 index 0000000..51b9cdf --- /dev/null +++ b/src/testCase/utTestBinary.erl @@ -0,0 +1,133 @@ +-module(utTestBinary). + +-compile([export_all, nowarn_unused_function, nowarn_unused_vars, nowarn_export_all]). + +genBinary(N) -> + list_to_binary([X rem 256 || X <- lists:seq(1, N)]). + +genList(N) -> + ([X rem 256 || X <- lists:seq(1, N)]). + +t0(N, Y) -> + Bin = genBinary(Y), + tt0(N, Bin). + +tt0(0, Bin) -> + ok; +tt0(N, Bin) -> + [X || <> <= Bin], + tt0(N - 1, Bin). + + +t1(N, Y) -> + Bin = genBinary(Y), + tt1(N, Bin). + +tt1(0, Bin) -> + ok; +tt1(N, Bin) -> + [X || <> <= Bin], + tt1(N - 1, Bin). + +t2(N, Y) -> + Bin = genBinary(Y), + tt2(N, Bin, Y div 2). + +tt2(0, Bin, Len) -> + ok; +tt2(N, Bin, Len) -> + deInt16List(Len, Bin, []), + tt2(N - 1, Bin, Len). + +t3(N, Y) -> + Bin = genBinary(Y), + tt3(N, Bin, Y div 4). + +tt3(0, Bin, Len) -> + ok; +tt3(N, Bin, Len) -> + deInt32List(Len, Bin, []), + tt3(N - 1, Bin, Len). + +deInt16List(0, MsgBin, RetList) -> + {lists:reverse(RetList), MsgBin}; +deInt16List(N, MsgBin, RetList) -> + <> = MsgBin, + deInt16List(N - 1, LeftBin, [Int | RetList]). + +deInt32List(0, MsgBin, RetList) -> + {lists:reverse(RetList), MsgBin}; +deInt32List(N, MsgBin, RetList) -> + <> = MsgBin, + deInt32List(N - 1, LeftBin, [Int | RetList]). + +-define(int16(V), <>). +-define(int32(V), <>). + +t4(N, Y) -> + List = genList(Y), + tt4(N, List). + +tt4(0, List) -> + ok; +tt4(N, List) -> + _ = [<> || V <- List], + tt4(N - 1, List). + + +t5(N, Y) -> + List = genList(Y), + tt5(N, List). + +tt5(0, List) -> + ok; +tt5(N, List) -> + _ = [<<(length(List)):16/big>>, [<> || V <- List]], + tt5(N - 1, List). + +t44(N, Y) -> + List = genList(Y), + tt44(N, List). + +tt44(0, List) -> + ok; +tt44(N, List) -> + <<<> || V <- List>>, + tt44(N - 1, List). + + +t6(N, Y) -> + List = genList(Y), + tt6(N, List). + +tt6(0, List) -> + ok; +tt6(N, List) -> + _ = [<<(length(List)):16/big>>, <<<> || V <- List>>], + tt6(N - 1, List). + +t7(N, Y) -> + List = genList(Y), + tt7(N, List). + +tt7(0, List) -> + ok; +tt7(N, List) -> + _ = <<(<<(length(List)):16/big>>)/binary, (<<<> || V <- List>>)/binary>>, + tt7(N - 1, List). + +t8(N, Y) -> + List = genList(Y), + tt4(N, List). + +tt8(0, List) -> + ok; +tt8(N, List) -> + < <<1>>; _ -> <<0>> end end || V <- List>>, + tt4(N - 1, List). + + + + + + diff --git a/src/testCase/utTestMap.erl b/src/testCase/utTestMap.erl new file mode 100644 index 0000000..6e4d6ca --- /dev/null +++ b/src/testCase/utTestMap.erl @@ -0,0 +1,49 @@ +-module(utTestMap). + +-compile([export_all, nowarn_unused_function, nowarn_unused_vars, nowarn_export_all]). + +t1(N) -> + Map = #{etime => {make_ref(), test}, stime => {make_ref(), test}, other => [1212, 132,3242,768]}, + tt1(N, Map). + +tt1(0, Map) -> + Map; +tt1(N, Map) -> + Key = etime, + case Map of + #{Key := {Ref, Msg}} -> + _ = {Ref, Msg}; + _ -> + not_found + end, + tt1(N - 1, Map). + +t2(N) -> + Map = #{etime => {make_ref(), test}, stime => {make_ref(), test}, other => [1212, 132,3242,768]}, + tt2(N, Map). + +tt2(0, Map) -> + Map; +tt2(N, Map) -> + case maps:find(etime1, Map) of + {ok, A} -> + A; + _ -> + not_found + end, + tt2(N - 1, Map). + +t3(N) -> + Map = #{etime => {make_ref(), test}, stime => {make_ref(), test}, other => [1212, 132,3242,768]}, + tt3(N, Map). + +tt3(0, Map) -> + Map; +tt3(N, Map) -> + case maps:get(etime, Map, not_found) of + {_Ref, _Msg} = A -> + A; + _ -> + not_found + end, + tt3(N - 1, Map). diff --git a/src/testCase/utTestMd5.erl b/src/testCase/utTestMd5.erl new file mode 100644 index 0000000..8d71010 --- /dev/null +++ b/src/testCase/utTestMd5.erl @@ -0,0 +1,139 @@ +-module(utTestMd5). + +-compile([export_all, nowarn_unused_function, nowarn_unused_vars, nowarn_export_all]). + +t1(N, Len) -> + Bin = list_to_binary([X rem 256 || X <- lists:seq(1, Len)]), + tt1(N, Bin, <<>>). + +%% 这种方式更快 +tt1(0, _Bin, Md5) -> + Md5; +tt1(N, Bin, _Md5) -> + Md5 = erlang:md5(Bin), + tt1(N - 1, Bin, Md5). + +t2(N, Len) -> + Bin = list_to_binary([X rem 256 || X <- lists:seq(1, Len)]), + tt2(N, Bin, <<>>). + +tt2(0, _Bin, Md5) -> + Md5; +tt2(N, Bin, _Md5) -> + Md5 = crypto:hash(md5, Bin), + tt2(N - 1, Bin, Md5). + +t3(N, Len) -> + Bin = list_to_binary([X rem 256 || X <- lists:seq(1, Len)]), + Md5Bin = erlang:md5(Bin), + tt3(N, Md5Bin, <<>>). + +tt3(0, _Md5Bin, HexStr) -> + HexStr; +tt3(N, Md5Bin, _HexStr) -> + <> = Md5Bin, + HexStr =string:to_lower(integer_to_list(Hash, 16)), + tt3(N - 1, Md5Bin, HexStr). + +t4(N, Len) -> + Bin = list_to_binary([X rem 256 || X <- lists:seq(1, Len)]), + Md5Bin = erlang:md5(Bin), + tt4(N, Md5Bin, <<>>). + +tt4(0, _Md5Bin, HexStr) -> + HexStr; +tt4(N, Md5Bin, _HexStr) -> + HexStr = lists:flatten([io_lib:format("~2.16.0b", [X]) || X <- binary_to_list(Md5Bin)]), + tt4(N - 1, Md5Bin, HexStr). + +%% 这种方式更加快 快好几倍呢 +t5(N, Len) -> + Bin = list_to_binary([X rem 256 || X <- lists:seq(1, Len)]), + Md5Bin = erlang:md5(Bin), + tt5(N, Md5Bin, <<>>). + +tt5(0, _Md5Bin, HexStr) -> + HexStr; +tt5(N, Md5Bin, _HexStr) -> + HexStr = utHex:binaryToHex(Md5Bin), + tt5(N - 1, Md5Bin, HexStr). + +deHex(H) when H >= $a, H =< $f -> H - $a + 10; +deHex(H) when H >= $A, H =< $F -> H - $A + 10; +deHex(H) when H >= $0, H =< $9 -> H - $0. + +t6(N) -> + HexBin = "b59c67bf196a4758191e42f76670ceba", + tt6(N, HexBin, []). + +tt6(0, _HexBin, List) -> + List; +tt6(N, HexBin, _List) -> + HexBin1 = list_to_binary(HexBin), + List = [(deHex(X1) * 16 + deHex(X2)) || <> <= HexBin1], + tt6(N - 1, HexBin, List). + +%% 这种方式更加快 快好几倍呢 +t7(N) -> + Hex = "b59c67bf196a4758191e42f76670ceba", + tt7(N, Hex). + +tt7(0, Hex) -> + {String, _} = + lists:foldr( + fun(E, {Acc, nolow}) -> + {Acc, deHex(E)}; + (E, {Acc, LO}) -> + {[deHex(E) * 16 + LO | Acc], nolow} + end, + {[], nolow}, Hex), + String; +tt7(N, Hex) -> + {String, _} = + lists:foldr( + fun(E, {Acc, nolow}) -> + {Acc, deHex(E)}; + (E, {Acc, LO}) -> + {[deHex(E) * 16 + LO | Acc], nolow} + end, + {[], nolow}, Hex), + String, + tt7(N - 1, Hex). + +u1(0) -> + crypto:strong_rand_bytes(16); +u1(N) -> + crypto:strong_rand_bytes(16), + u1(N - 1). + + +u2(0) -> + erlang:md5(term_to_binary({erlang:system_time(nanosecond), rand:uniform(134217727), make_ref()})); +u2(N) -> + erlang:md5(term_to_binary({erlang:system_time(nanosecond), rand:uniform(134217727), make_ref()})), + u2(N - 1). + +u3(0) -> + crypto:strong_rand_bytes(4); +u3(N) -> + crypto:strong_rand_bytes(4), + u3(N - 1). + +u33(0) -> + rand:uniform(2100000000); +u33(N) -> + rand:uniform(2100000000), + u33(N - 1). + +u333(0) -> + erlang:localtime(); +u333(N) -> + erlang:localtime(), + u333(N - 1). + +u4(0) -> + erlang:md5(integer_to_list(erlang:phash2({os:system_time(micro_seconds), make_ref(), make_ref()}))); +u4(N) -> + erlang:md5(integer_to_list(erlang:phash2({os:system_time(micro_seconds), make_ref(), make_ref()}))), + u1(N - 1). + diff --git a/src/testCase/utTestPerformance.erl b/src/testCase/utTestPerformance.erl new file mode 100644 index 0000000..1de9438 --- /dev/null +++ b/src/testCase/utTestPerformance.erl @@ -0,0 +1,161 @@ +-module(utTestPerformance). + + +-compile([export_all, nowarn_unused_function, nowarn_unused_vars, nowarn_export_all]). + +-record(cycleData, { + module = test + , isEnter = false + , hibernateAfter = infinity + , isHibernate = false + , lastStatus = init_status + , lastState = #{11 => 555, 44 => 434} + , postponed = [1,3,"dffd", "fdf"] + , timers = #{etime => {aaa, fdfd}} +}). + +tt1(N) -> + tt1(N, #cycleData{}, [123421,434,34], {12222,343, "fdfd"}, fff, "ArgD"). + +tt1(0, CycleData, ArgA, ArgB, ArgC, ArgD) -> + ok; +tt1(N, #cycleData{lastState = LastState, isEnter = IsEnter, hibernateAfter = HibernateAfter, module = Module} = CycleData, ArgA, ArgB, ArgC, ArgD) -> + I1 = is_atom(LastState), + I2 = is_atom(IsEnter), + I3 = is_atom(HibernateAfter), + I4 = is_atom(Module), + _Ret = I1 andalso I2 andalso I3 andalso I4 andalso true, + tt1(N - 1, CycleData, ArgA, ArgB, ArgC, ArgD). + +tt2(N) -> + tt2(N, #cycleData{}, [123421,434,34], {12222,343, "fdfd"}, fff, "ArgD"). + +tt2(0, CycleData, ArgA, ArgB, ArgC, ArgD) -> + ok; +tt2(N, CycleData, ArgA, ArgB, ArgC, ArgD) -> + LastState = element(#cycleData.lastState, CycleData), + IsEnter = element(#cycleData.isEnter, CycleData), + HibernateAfter= element(#cycleData.hibernateAfter, CycleData), + Module = element(#cycleData.module, CycleData), + I1 = is_atom(LastState), + I2 = is_atom(IsEnter), + I3 = is_atom(HibernateAfter), + I4 = is_atom(Module), + _Ret = I1 andalso I2 andalso I3 andalso I4 andalso true, + tt2(N -1, CycleData, ArgA, ArgB, ArgC, ArgD). + +tt3(N) -> + tt3(N, #cycleData{}, [123421,434,34], {12222,343, "fdfd"}, fff, "ArgD"). + +tt3(0, CycleData, ArgA, ArgB, ArgC, ArgD) -> + ok; +tt3(N, CycleData, ArgA, ArgB, ArgC, ArgD) -> + NewCycleData = CycleData#cycleData{module = tttt, lastState = #{11 => 22, 22 => 33}, isEnter = false}, + tt3(N - 1, NewCycleData, ArgA, ArgB, ArgC, ArgD). + +tt4(N) -> + tt4(N, #cycleData{}, [123421,434,34], {12222,343, "fdfd"}, fff, "ArgD"). + +tt4(0, CycleData, ArgA, ArgB, ArgC, ArgD) -> + ok; +tt4(N, CycleData, ArgA, ArgB, ArgC, ArgD) -> + New1 = setelement(#cycleData.module, CycleData, tttt), + New2 = setelement(#cycleData.lastState, New1, #{11 => 22, 22 => 33}), + New3 = setelement(#cycleData.isEnter, New2, false), + tt4(N -1, New3, ArgA, ArgB, ArgC, ArgD). + +tt5(N) -> + tt5(N, #cycleData{}, [123421,434,34]). + +tt5(0, CycleData, AA) -> + ok; +tt5(N, CycleData, AA) -> + tt5(N - 1, CycleData, AA). + +tt6(N) -> + tt6(N,test, false, infinity, false, init_status, #{11 => 555, 44 => 434}, [1,3,"dffd", "fdf"], #{etime => {aaa, fdfd}}, [123421,434,34]). + +tt6(0, A1, B, C, D, E, F, G, H, AA) -> + ok; +tt6(N, A1, B, C, D, E, F, G, H, AA) -> + tt6(N -1, A1, B, C, D, E, F, G, H, AA). + +tt7(0) -> + ok; +tt7(N) -> + tt7(N -1). + + +tt8(N) -> + tt8(N, #cycleData{}). + +tt8(0, CycleData) -> + ok; +tt8(N, #cycleData{module = Module, lastState = Lasst, postponed = Postponed} = AA) -> + A = setelement(#cycleData.module, AA, ttt), + B = setelement(#cycleData.isEnter, A, trye), + %% B = setelement(#cycleData.lastState, A, #{22 => 555, 55 => 434}), + %% C = setelement(#cycleData.postponed, B, [1,3,"fdf", "dffd"]), + tt8(N - 1, B). + +tt88(N) -> + tt88(N, #cycleData{}). + +tt88(0, CycleData) -> + ok; +tt88(N, #cycleData{module = Module, lastState = Lasst, postponed = Postponed} = AA) -> + %%C = setelement(#cycleData.postponed, AA, [1,3,"fdf", "dffd"]), + %%B = setelement(#cycleData.lastState, C, #{22 => 555, 55 => 434}), + B = setelement(#cycleData.isEnter, AA, trye), + A = setelement(#cycleData.module, B, ttt), + tt88(N - 1, A). + +tt888(N) -> + tt888(N, #cycleData{}). + +tt888(0, CycleData) -> + ok; +tt888(N, #cycleData{module = Module, lastState = Lasst, postponed = Postponed} = AA) -> + A = AA#cycleData{isEnter = trye, module = ttt}, + tt888(N - 1, A). + +tt9(N) -> + Data = #cycleData{}, + put(a, Data#cycleData.module), + put(b, Data#cycleData.isEnter), + put(c, Data#cycleData.hibernateAfter), + put(d, Data#cycleData.isHibernate), + put(e, Data#cycleData.lastStatus), + put(f, Data#cycleData.lastState), + put(g, Data#cycleData.postponed), + tt10(N). + +tt10(0) -> + ok; +tt10(N) -> + A = get(a), + put(a, ttt), + B = get(f), + put(f, #{22 => 555, 55 => 434}), + C = get(g), + put(g, [1,3,"fdf", "dffd"]), + _Ret = A orelse B orelse C orelse true, + tt10(N -1). + +c6(N) -> + cc6(N, 0). + +cc6(0, F) -> + F; +cc6(N, _F) -> + F = N + 0.0, + cc6(N - 1, F). + +c7(N) -> + cc7(N, 0). + +cc7(0, F) -> + F; +cc7(N, _F) -> + F = float(N), + cc7(N - 1, F). diff --git a/src/testCase/utTestRand.erl b/src/testCase/utTestRand.erl new file mode 100644 index 0000000..050e25c --- /dev/null +++ b/src/testCase/utTestRand.erl @@ -0,0 +1,53 @@ +-module(utTestRand). +%%该测试用于测试 全服每天随机某个值 检查改算法的随机性 主要用于测试该算法的随机平均概率值 + +-compile([export_all, nowarn_unused_function, nowarn_unused_vars, nowarn_export_all]). + +tt0(Month, Len) -> + erase(), + randDay(31, Len, Month). + + + +randDay(0, Len, Month) -> + print(Len), + ok; +randDay(CurDay, Len, Month) -> + TemRand = 2019 + Month * 167 + CurDay * 313 + 2 * 131, + N = TemRand rem Len + 1, + io:format("IMY************randDay ~p ~p ~n", [CurDay, N]), + add(N), + randDay(CurDay - 1, Len, Month). + +tt1(Day, Len) -> + erase(), + randDay1(Day, Len). + + + +randDay1(0, Len) -> + print(Len), + ok; +randDay1(CurDay, Len) -> + TemRand = CurDay * 11, + N = TemRand rem Len + 1, + io:format("IMY************randDay ~p ~p ~n", [CurDay, N]), + add(N), + randDay1(CurDay - 1, Len). + +add(N) -> + case erlang:get(N) of + undefined -> + erlang:put(N, 1); + V -> + erlang:put(N, 1 + V) + end. + +print(0) -> + ok; +print(N) -> + io:format("IMY************ ~p ~p ~n", [N, erlang:get(N)]), + print(N - 1). + + + diff --git a/src/testCase/utTestTime.erl b/src/testCase/utTestTime.erl new file mode 100644 index 0000000..4cef0c6 --- /dev/null +++ b/src/testCase/utTestTime.erl @@ -0,0 +1,270 @@ +-module(utTestTime). + +-compile([export_all, nowarn_unused_function, nowarn_export_all]). + +-define(SECS_1970, 62167219200). %%utc 1970年经历过的秒数 + +t1(N, Fun) -> + LocalTime = erlang:localtime(), + tt1(N, LocalTime, Fun). + +tt1(0, LocalTime, Fun) -> + ?MODULE:Fun(LocalTime); +tt1(N, LocalTime, Fun) -> + ?MODULE:Fun(LocalTime), + tt1(N - 1, LocalTime, Fun). + +t2(N, Fun) -> + Sec = erlang:system_time(second), + tt2(N, Sec, Fun). + +tt2(0, Sec, Fun) -> + ?MODULE:Fun(Sec); +tt2(N, Sec, Fun) -> + ?MODULE:Fun(Sec), + tt2(N - 1, Sec, Fun). + +%% 经过测试 ls1 和 sl1 效率最高 +%%%%%%%%%%%%%%%%% datetime 和 timestamp 互相转换 测试对比函数 start %%%%%%%%%%%%%%%%%%% +ls1(LocalDate) -> + erlang:universaltime_to_posixtime(erlang:localtime_to_universaltime(LocalDate)). + + +%% 此方法很准 +ls2(DateTime) -> + UDateTime = erlang:localtime_to_universaltime(DateTime), + calendar:datetime_to_gregorian_seconds(UDateTime) - ?SECS_1970. + +ls3(DateTime) -> + case calendar:local_time_to_universal_time_dst(DateTime) of + [] -> false; + [_, Udate] -> + calendar:datetime_to_gregorian_seconds(Udate) - ?SECS_1970; + [Udate] -> + calendar:datetime_to_gregorian_seconds(Udate) - ?SECS_1970 + end. + +ls4(DateTime) -> + calendar:datetime_to_gregorian_seconds(DateTime) - 62167248000. + + +us1(UniversalTime) -> + erlang:universaltime_to_posixtime(UniversalTime). + +%% 将秒单位的时间戳 转为世界 datetime() +su1(Ses) -> + erlang:posixtime_to_universaltime(Ses). + +%% 将秒单位的时间戳 转为本地 datetime() +sl1(Ses) -> + erlang:universaltime_to_localtime(erlang:posixtime_to_universaltime(Ses)). + +sl2(Ses) -> + DateTime = calendar:gregorian_seconds_to_datetime(Ses + ?SECS_1970), + calendar:universal_time_to_local_time(DateTime). + +sl3(Ses) -> + T1 = Ses div 1000000, + T2 = Ses - T1 * 1000000, + T = calendar:now_to_datetime({T1, T2, 0}), + calendar:universal_time_to_local_time(T). + +%%%%%%%%%%%%%%%%% datetime 和 timestamp 测试对比函数 end %%%%%%%%%%%%%%%%%%%%%%%%%% + +t3(N, Fun) -> + Sec1 = erlang:system_time(second), + Sec2 = Sec1 - rand:uniform(1000000), + tt3(N, Sec1, Sec2, Fun). + +tt3(0, Sec1, Sec2, Fun) -> + ?MODULE:Fun(Sec1, Sec2); +tt3(N, Sec1, Sec2, Fun) -> + ?MODULE:Fun(Sec1, Sec2), + tt3(N - 1, Sec1, Sec2, Fun). + +%%%%%%%%%%%%%%%%% IsSame*** 测试对比函数 start %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +isd1(Sec1, Sec2) -> + NDay = Sec1 div 86400, + ODay = Sec2 div 86400, + NDay =:= ODay. + +isd11(Sec1, Sec2) -> + Sec1 div 86400 =:= Sec2 div 86400. + + +isd2(Sec1, Sec2) -> + {Date1, _Time1} = sl1(Sec1), + {Date2, _Time2} = sl1(Sec2), + Date1 =:= Date2. + +isw11(Sec1, Sec2) -> + (Sec1 + 345600) div 604800 =:= (Sec2 + 345600) div 604800. + +isw1(Sec1, Sec2) -> + {{Year1, Month1, Day1}, Time1} = sl1(Sec1), + % 星期几 + Week1 = calendar:day_of_the_week(Year1, Month1, Day1), + % 从午夜到现在的秒数 + Diff1 = calendar:time_to_seconds(Time1), + Monday = Sec1 - Diff1 - (Week1 - 1) * 86400, + Sunday = Sec1 + (86400 - Diff1) + (7 - Week1) * 86400, + if ((Sec2 >= Monday) and (Sec2 < Sunday)) -> true; + true -> false + end. + +day_of_the_week(UnixTime) -> + {{Y, M, D}, _} = sl1(UnixTime), + calendar:day_of_the_week(Y, M ,D). + +%% @doc 返回相应类型的unix时间戳 +%%
    +%%
  • ms: 取得当前的unix时间戳,精确到毫秒
  • +%%
  • today: 获取当天0时0分0秒的时间戳
  • +%%
  • {today, Ts}: 根据给出的时间戳,获取与该时间戳同一天的零时。当时间为0时,返回值有可能是负值,因为这里有时区偏移值(例如北京时间就可能是-28800)
  • +%%
  • {tomorrow, Ts}: 根据给出的时间戳,获取该时间戳第二天的零时
  • +%%
  • {next_time, Ts}::根据给出的时间间隔(距离0点的时间, 如3600),取出下一个该时间戳
  • +%%
+-spec unixtime(X) -> pos_integer() when + X :: ms | today | {today, pos_integer()} | {next_day, pos_integer()}. +unixtime(ms) -> + %% {S1, S2, S3} = erlang:now(), + {S1, S2, S3} = os:timestamp(), + trunc(S1 * 1000000000 + S2 * 1000 + S3 / 1000); +unixtime(today) -> + {M, S, MS} = os:timestamp(), + {_, Time} = calendar:now_to_local_time({M, S, MS}), + M * 1000000 + S - calendar:time_to_seconds(Time); +unixtime(tomorrow) -> + unixtime(today) + 86400; +unixtime({today, Ts}) -> + Base = unixtime(today), + case Ts > Base of + false -> Base - util:ceil((Base - Ts) / 86400) * 86400; + true -> (Ts - Base) div 86400 * 86400 + Base + end; +unixtime({tomorrow, Ts}) -> + unixtime({today, Ts}) + 86400; +unixtime({next_time, DayTs}) -> + Now = erlang:system_time(second), + NextT = next_diff(DayTs), + Now + NextT. + +%% @doc 当前距离N天后某时刻的相差秒数 +-spec now_diff(N, {H, I, S}) -> integer() when + N :: today | tomorrow | non_neg_integer(), + H :: 0..23, + I :: 0..59, + S :: 0..59. +now_diff(today, {H, I, S}) -> + now_diff(0, {H, I, S}); +now_diff(tomorrow, {H, I, S}) -> + now_diff(1, {H, I, S}); +now_diff(N, {H, I, S}) when is_integer(N), N >= 0 -> + {_, Time} = calendar:local_time(), + N * 86400 + calendar:time_to_seconds({H, I, S}) - calendar:time_to_seconds(Time). + +-spec next_diff(0..86400 | [0..86400]) -> Seconds::pos_integer(). +next_diff(L = [_ | _]) -> + lists:min([next_diff(Sec) || Sec <- L]); +next_diff(Sec) -> + Now = erlang:system_time(second), + Zero = unixtime({today, Now}), + Base = Zero + Sec, %% 取当天距离X的时间为指定时间 + case Base > Now of + true -> Base - Now; %% 当前时间比指定时间小 直接返回差距 + false -> Base + 86400 - Now %% 当前时间比指定时间大 加上一天时间后求差 + end. + +isw2(0, Ts2) when Ts2 > 0 -> false; +isw2(Ts1, 0) when Ts1 > 0 -> false; +isw2(Ts, Ts) -> true; +isw2(Ts1, Ts2) -> + Dw = day_of_the_week(Ts1), + Zero = unixtime({today, Ts1}), + Beg = Zero - 86400 * (Dw-1), + End = Zero + 86400 * (8-Dw), + Ts2 >= Beg andalso Ts2 < End. + +ism1(Sec1, Sec2) -> + {{Year1, Month1, _Day1}, _Time1} = sl1(Sec1), + {{Year2, Month2, _Day2}, _Time2} = sl1(Sec2), + Month1 =:= Month2 andalso Year1 =:= Year2. + +ism2(Sec1, Sec2) -> + {{Year1, Month1, _Day1}, _Time1} = sl1(Sec1), + Begin = ls1({{Year1, Month1, 1}, {0, 0, 0}}), + EndDay = calendar:last_day_of_the_month(Year1, Month1), + End = Begin + EndDay * 86400, + Sec2 >= Begin andalso Sec2 =< End. + +%%%%%%%%%%%%%%%%% IsSame*** 测试对比函数 end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%% **Begin **End 测试对比函数 start %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +timeZoneDiff() -> + UTC2001 = {{2001, 1, 1}, {0, 0, 0}}, + %% 将1970年时间由世界时间转为本地时间 + Local2001 = erlang:universaltime_to_localtime(UTC2001), + %% 计算2001世界时间的秒时间戳 + % UTC2001Sec = calendar:datetime_to_gregorian_seconds(UTC2001), + %% UTC2001Sec = 63145526400, + %% 计算2001年本地时间的时间戳 + %% Local2001Sec = calendar:datetime_to_gregorian_seconds(Local2001), + %% Local2001Sec - UTC2001Sec. + erlang:universaltime_to_posixtime(Local2001) - 978307200. + +hs1(Sec) -> + Sec - Sec rem 3600. + +ds1(Sec) -> + Sec - (Sec + timeZoneDiff()) rem 86400. + + +ws1(Sec) -> + Sec - (Sec - 345600 + timeZoneDiff()) rem 604800. + +ms1(Sec) -> + {Days, _Time} = calendar:seconds_to_daystime(Sec + ?SECS_1970), + {Y, M, _D} = calendar:gregorian_days_to_date(Days), + MonthStartDateTime = {{Y, M, 1}, {0, 0, 0}}, + ls1(MonthStartDateTime). + +ms2(Sec) -> + {{Year, Month, _Day}, _Time} = su1(Sec), + MonthStartDateTime = {{Year, Month, 1}, {0, 0, 0}}, + ls1(MonthStartDateTime). + +%%%%%%%%%%%%%%%%% **Begin **End 测试对比函数 end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +t4(N, Fun) -> + persistent_term:put(zonediff, 28800), + tt4(N, Fun). + +tt4(0, Fun) -> + ?MODULE:Fun(); +tt4(N, Fun) -> + ?MODULE:Fun(), + tt4(N - 1, Fun). + +zone1() -> + persistent_term:get(zonediff, 28800). + + +zone2() -> + Local2001 = erlang:universaltime_to_localtime({{2001, 1, 1}, {0, 0, 0}}), + io:format("IMY**************** ~p~n",[Local2001]), + erlang:universaltime_to_posixtime(Local2001) - 978307200. + +zone3() -> + NowTime = erlang:universaltime(), + LoTime = erlang:universaltime_to_localtime(NowTime), + io:format("IMY**************** ~p~n",[NowTime]), + io:format("IMY**************** ~p~n",[LoTime]), + erlang:universaltime_to_posixtime(LoTime) - erlang:universaltime_to_posixtime(NowTime). + +tk1() -> + erlang:system_time(microsecond). + +tk2() -> + os:system_time(microsecond). + +tk3() -> + erlang:system_time(nanosecond). diff --git a/src/testCase/utTestTrace.erl b/src/testCase/utTestTrace.erl new file mode 100644 index 0000000..cb60013 --- /dev/null +++ b/src/testCase/utTestTrace.erl @@ -0,0 +1,179 @@ +-module(utTestTrace). + +-compile([export_all, nowarn_unused_function, nowarn_unused_vars, nowarn_export_all]). + + +t1() -> + Pid = spawn(fun() -> do_t1(1) end), + send_msg(Pid, 100000). + +t2() -> + Pid = spawn(fun() -> do_t2(1) end), + send_msg(Pid, 100000). + +send_msg(Pid, 0) -> + io:format("IMY***********send_msg over ~p ~n ~p ~n", [0, Pid]), + ok; +send_msg(Pid, N) -> + Pid ! <<2:(N)>>, + % timer:sleep(1), + send_msg(Pid, N - 1). + +do_t1(N) -> + case N == 1 orelse N == 90000 of + true -> + erlang:garbage_collect(), + Result = erlang:process_info(self(), [memory, garbage_collection]), + io:format("IMY************************* ~p~n ~w ~n", [N, Result]); + %io:format("IMY&&&&&&&&&&&&&&&&&&&&&&&&& ~p~n backtrace:~p~n~n", [N, erlang:process_display(self(), backtrace)]); + _ -> + ignore + end, + + try + receive + _ -> + ok + %% do_t1(N + 1) + end, + do_t1(N + 1) + catch + _:_ -> + do_t1(N + 1) + end. + +do_t2(N) -> + case N == 1 orelse N == 90000 of + true -> + erlang:garbage_collect(), + Result = erlang:process_info(self(), [memory, garbage_collection]), + io:format("IMY************************* ~p ~n ~w ~n", [N, Result]), + io:format("IMY&&&&&&&&&&&&&&&&&&&&&&&&& ~p ~n backtrace:~w~n~n", [N, erlang:process_display(self(), backtrace)]); + _ -> + %io:format("IMY************************* ~p ~n", [N]), + ignore + end, + receive + _ -> + do_t2(N + 1) + end. + +desult3(N, State) -> + %io:format("IMy*********************desult3 ~p~n",[N]), + do_t3(N). + +desult4(N, State) -> + do_t4(N). + +t3() -> + Pid = spawn(fun() -> do_t3(100000) end). + +t4() -> + Pid = spawn(fun() -> do_t4(100000) end). + +do_t3(0) -> + io:format("IMy*********************dfdfdffd33333333"); +do_t3(N) -> + case N == 1 orelse N == 99999 of + true -> + erlang:garbage_collect(), + Result = erlang:process_info(self(), [memory, garbage_collection]), + io:format("IMY************************* ~p~n ~w ~n", [N, Result]), + io:format("IMY&&&&&&&&&&&&&&&&&&&&&&&&& ~p~n backtrace:~p~n~n", [N, erlang:process_display(self(), backtrace)]); + _ -> + ignore + end, + + try test:tt9(2) of + Ret -> + desult3(N - 1, Ret) + catch + _:_ -> + desult3(N - 1, error) + end. +do_t4(0) -> + io:format("IMy*********************dfdfdffd44444444444"); +do_t4(N) -> + case N == 1 orelse N == 99999 of + true -> + erlang:garbage_collect(), + Result = erlang:process_info(self(), [memory, garbage_collection]), + io:format("IMY************************* ~p ~n ~w ~n", [N, Result]), + io:format("IMY&&&&&&&&&&&&&&&&&&&&&&&&& ~p ~n backtrace:~w~n~n", [N, erlang:process_display(self(), backtrace)]); + _ -> + %io:format("IMY************************* ~p ~n", [N]), + ignore + end, + Ret1 = try test:tt9(2) of + Ret -> + Ret + catch + _:_ -> + error + end, + do_t4(N - 1). + +do_t5(0) -> + io:format("IMy*********************dfdfdffd55555555555555"); +do_t5(N) -> + case N == 1 orelse N == 99999 of + true -> + erlang:garbage_collect(), + Result = erlang:process_info(self(), [memory, garbage_collection]), + io:format("IMY************************* ~p ~n ~w ~n", [N, Result]), + io:format("IMY&&&&&&&&&&&&&&&&&&&&&&&&& ~p ~n backtrace:~w~n~n", [N, erlang:process_display(self(), backtrace)]); + _ -> + %io:format("IMY************************* ~p ~n", [N]), + ignore + end, + try test:tt9(2) of + Ret -> + do_t5(N - 1) + catch + _:_ -> + error + end. + +do_t6(0) -> + io:format("IMy*********************dfdfdffd55555555555555"); +do_t6(N) -> + case N == 1 orelse N == 99999 of + true -> + erlang:garbage_collect(), + Result = erlang:process_info(self(), [memory, garbage_collection]), + io:format("IMY************************* ~p ~n ~w ~n", [N, Result]); + %io:format("IMY&&&&&&&&&&&&&&&&&&&&&&&&& ~p ~n backtrace:~w~n~n", [N, erlang:process_display(self(), backtrace)]); + _ -> + %io:format("IMY************************* ~p ~n", [N]), + ignore + end, + try test:tt9(2) of + Ret -> + do_t6(N - 1) + catch + _:_ -> + error + %after + % ok + end. + +do_t7(0) -> + io:format("IMy********************11111"); +do_t7(N) -> + io:format("IMy********************22222"), + try test:tt9(2) of + _Ret -> + io:format("IMy********************3333"), + do_t7(N - 1) + catch + throw:ret -> + io:format("IMy********************4444"), + do_t7(N - 1); + _:_ -> + io:format("IMy********************5555"), + error + end. + + + + diff --git a/src/testCase/utTimeCase.erl b/src/testCase/utTimeCase.erl new file mode 100644 index 0000000..5a5788e --- /dev/null +++ b/src/testCase/utTimeCase.erl @@ -0,0 +1,58 @@ +-module(utTimeCase). + +-compile([export_all, nowarn_unused_function, nowarn_unused_vars, nowarn_export_all]). + +t1(N) -> + tt1(N, 0). + +tt1(0, Time) -> + Time; +tt1(N, _Time) -> + Time = time(), + tt1(N - 1, Time). + +t2(N) -> + tt2(N, 0). + +tt2(0, Date) -> + Date; +tt2(N, _Date) -> + Date = date(), + tt2(N - 1, Date). + +t3(N) -> + tt3(N, 0). + +tt3(0, Ms) -> + Ms; +tt3(N, _Ms) -> + Ms = erlang:system_time(millisecond), + tt3(N - 1, Ms). + +t4(N) -> + tt4(N, 0). + +tt4(0, Ns) -> + Ns; +tt4(N, _Ns) -> + Ns = erlang:system_time(second), + tt4(N - 1, Ns). + +t5(N) -> + tt5(N, 0). + +tt5(0, Tt) -> + Tt; +tt5(N, _Tt) -> + Tt = os:timestamp(), + tt5(N - 1, Tt). + +t6(N) -> + tt6(N, 0). + +tt6(0, Tt) -> + Tt; +tt6(N, _Tt) -> + {MegaSecs, Secs, _MicroSecs} = os:timestamp(), + Tt = MegaSecs * 1000000 + Secs, + tt6(N - 1, Tt). diff --git a/src/testCase/utTryCatchCase.erl b/src/testCase/utTryCatchCase.erl new file mode 100644 index 0000000..8eb4d07 --- /dev/null +++ b/src/testCase/utTryCatchCase.erl @@ -0,0 +1,201 @@ +-module(utTryCatchCase). + +-compile([export_all, nowarn_unused_function, nowarn_unused_vars, nowarn_export_all]). + + +t1() -> + Pid = spawn(fun() -> do_t1(1) end), + send_msg(Pid, 100000). + +t2() -> + Pid = spawn(fun() -> do_t2(1) end), + send_msg(Pid, 100000). + +send_msg(Pid, 0) -> + io:format("IMY***********send_msg over ~p ~n ~p ~n", [0, Pid]), + ok; +send_msg(Pid, N) -> + Pid ! <<2:(N)>>, + % timer:sleep(1), + send_msg(Pid, N - 1). + +do_t1(N) -> + case N == 1 orelse N == 90000 of + true -> + erlang:garbage_collect(), + Result = erlang:process_info(self(), [memory, garbage_collection]), + io:format("IMY************************* ~p~n ~w ~n", [N, Result]); + %io:format("IMY&&&&&&&&&&&&&&&&&&&&&&&&& ~p~n backtrace:~p~n~n", [N, erlang:process_display(self(), backtrace)]); + _ -> + ignore + end, + + + try + receive + _ -> + ok + %% do_t1(N + 1) + end, + do_t1(N + 1) + catch + _:_ -> + do_t1(N + 1) + end. + +do_t2(N) -> + case N == 1 orelse N == 90000 of + true -> + erlang:garbage_collect(), + Result = erlang:process_info(self(), [memory, garbage_collection]), + io:format("IMY************************* ~p ~n ~w ~n", [N, Result]), + io:format("IMY&&&&&&&&&&&&&&&&&&&&&&&&& ~p ~n backtrace:~w~n~n", [N, erlang:process_display(self(), backtrace)]); + _ -> + %io:format("IMY************************* ~p ~n", [N]), + ignore + end, + receive + _ -> + do_t2(N + 1) + end. + +desult3(N, State) -> + %io:format("IMy*********************desult3 ~p~n",[N]), + do_t3(N). + +desult4(N, State) -> + do_t4(N). + +t3() -> + Pid = spawn(fun() -> do_t3(100000) end). + +t4() -> + Pid = spawn(fun() -> do_t4(100000) end). + +t5() -> + Pid = spawn(fun() -> do_exit() end). + +do_t3(0) -> + io:format("IMy*********************dfdfdffd33333333"); +do_t3(N) -> + case N == 1 orelse N == 99999 of + true -> + erlang:garbage_collect(), + Result = erlang:process_info(self(), [memory, garbage_collection]), + io:format("IMY************************* ~p~n ~w ~n", [N, Result]), + io:format("IMY&&&&&&&&&&&&&&&&&&&&&&&&& ~p~n backtrace:~p~n~n", [N, erlang:process_display(self(), backtrace)]); + _ -> + ignore + end, + + try utFunCallCase:tt9(2) of + Ret -> + desult3(N - 1, Ret) + catch + _:_ -> + desult3(N - 1, error) + end. +do_t4(0) -> + io:format("IMy*********************dfdfdffd44444444444"); +do_t4(N) -> + case N == 1 orelse N == 99999 of + true -> + erlang:garbage_collect(), + Result = erlang:process_info(self(), [memory, garbage_collection]), + io:format("IMY************************* ~p ~n ~w ~n", [N, Result]), + io:format("IMY&&&&&&&&&&&&&&&&&&&&&&&&& ~p ~n backtrace:~w~n~n", [N, erlang:process_display(self(), backtrace)]); + _ -> + %io:format("IMY************************* ~p ~n", [N]), + ignore + end, + Ret1 = try utFunCallCase:tt9(2) of + Ret -> + Ret + catch + _:_ -> + error + end, + do_t4(N - 1). + +do_t5(0) -> + io:format("IMy*********************dfdfdffd55555555555555"); +do_t5(N) -> + case N == 1 orelse N == 99999 of + true -> + erlang:garbage_collect(), + Result = erlang:process_info(self(), [memory, garbage_collection]), + io:format("IMY************************* ~p ~n ~w ~n", [N, Result]), + io:format("IMY&&&&&&&&&&&&&&&&&&&&&&&&& ~p ~n backtrace:~w~n~n", [N, erlang:process_display(self(), backtrace)]); + _ -> + %io:format("IMY************************* ~p ~n", [N]), + ignore + end, + try utFunCallCase:tt9(2) of + Ret -> + do_t5(N - 1) + catch + _:_ -> + error + end. + + +do_t6(0) -> + io:format("IMy*********************dfdfdffd55555555555555"); + +do_t6(N) -> + case N == 1 orelse N == 99999 of + true -> + erlang:garbage_collect(), + Result = erlang:process_info(self(), [memory, garbage_collection]), + io:format("IMY************************* ~p ~n ~w ~n", [N, Result]); + %io:format("IMY&&&&&&&&&&&&&&&&&&&&&&&&& ~p ~n backtrace:~w~n~n", [N, erlang:process_display(self(), backtrace)]); + _ -> + %io:format("IMY************************* ~p ~n", [N]), + ignore + end, + try utFunCallCase:tt9(2) of + Ret -> + do_t6(N - 1) + catch + _:_ -> + error + %after + % ok + end. + +do_t7(0) -> + io:format("IMy********************11111"); +do_t7(N) -> + io:format("IMy********************22222"), + try utFunCallCase:tt9(2) of + _Ret -> + io:format("IMy********************3333"), + do_t7(N - 1) + catch + throw:ret -> + io:format("IMy********************4444"), + do_t7(N - 1); + _:_ -> + io:format("IMy********************5555"), + error + end. + +do_exit() -> + try + io:format("IMY**************************do_exit try111~n"), + io:format("IMY**************************do_exit try222~n"), + io:format("IMY**************************do_exit try333~n"), + io:format("IMY**************************do_exit try444~n"), + erlang:raise(error, test, []), + io:format("IMY**************************do_exit try555~n") + catch + _A -> + io:format("IMY**************************do_exit catch ~p ~n", [_A]) + after + io:format("IMY**************************do_exit after ~n") + end. + + + + + diff --git a/src/timeDate/time相关的日志.txt b/src/timeDate/time相关的日志.txt new file mode 100644 index 0000000..f0dfe0b --- /dev/null +++ b/src/timeDate/time相关的日志.txt @@ -0,0 +1,181 @@ +erlang 模块的时间函数---------》》》》 + +localtime_to_universaltime/1 + 如果基础操作系统支持,则将本地日期和时间转换为世界标准时间(UTC). 否则,不进行任何转换,并 返回Localtime + +localtime_to_universaltime/2 + 将本地日期和时间转换为erlang:localtime_to_universaltime / 1,以协调世界时(UTC),但调用者确定夏令时是否处于活动状态。 + 如果IsDst == true,则本地 时间位于夏令时,如果IsDst == false ,则不是。如果IsDst == undefined,则底层操作系统可以猜测, + 这与调用 erlang:localtime_to_universaltime(Localtime)相同。 + +universaltime_to_localtime/1 + 如果基础操作系统支持,则以{{Year,Month,Day},{Hour,Minute,Second}}的形式将世界标准时间(UTC)日期和时间转换为本地日期和时间 。 + 否则,不进行任何转换,并 返回Universaltime。例: + +time/0 + 以{Hour,Minute,Second}的形式返回当前时间。时区和夏令时校正取决于基础操作系统。 +date/0 + 返回当前日期为{Year,Month,Day}。时区和夏令时校正取决于基础操作系统。 + +localtime/0 + 返回当前的本地日期和时间 {{Year,Month,Day},{Hour,Minute,Second}} 时区和夏令时校正取决于基础操作系统。 + +universaltime/0 + 如果基础操作系统支持,则根据世界标准时间(UTC)以{{Year,Month,Day},{Hour,Minute,Second}}的形式返回当前日期和时间 。 + 否则,erlang:universaltime()等效于 erlang:localtime()。例: + +posixtime_to_universaltime/1 + posixtime 转为 universaltime +universaltime_to_posixtime/1 + universaltime换为posixtime时间戳 + +system_time/0, + 以本地时间单位返回当前的 Erlang系统时间。 + +system_time/1 + 返回当前的 Erlang系统时间, 该时间已转换为作为参数传递的Unit。 + +convert_time_unit/3 + 转换时间的时间单位的值 FromUnit到相应 ConvertedTime时间单元的值 ToUnit。使用下限功能对结果进行四舍五入。 + 警告:在时间单位之间进行转换时,可能会失去准确性和精度。为了最大程度地减少此类损失,请以本地时间单位收集所有数据,然后对最终结果进行转换。 +time_offset/0 + 以 本地时间单位返回Erlang单调时间和 Erlang系统时间之间的当前时间偏移 。添加到Erlang单调时间的当前时间偏移会给出相应的Erlang系统时间。 + 时间偏移可能会或可能不会在操作期间更改,具体取决于所使用的时间扭曲模式。 + 注意: + 通过不同的过程,可以在稍有不同的时间点观察到时间偏移量的变化。 + 如果运行时系统处于 多时间扭曲模式,则当运行时系统检测到OS系统时间已更改时,时间偏移也会 更改。但是,运行时系统不会立即检测到它。 + 检查时间偏移的任务计划至少每分钟执行一次;因此,在正常操作下,一分钟内即可检测到,但是在重负载下可能需要更长的时间。 + +time_offset/1 + 返回Erlang单调时间和 Erlang系统时间之间的当前时间偏移, 该时间已转换为作为参数传递的Unit。 + +timestamp/0 + 以{MegaSecs,Secs,MicroSecs}格式返回当前的 Erlang系统时间。此格式与os:timestamp / 0 和不赞成使用的erlang:now / 0相同 。 + 存在erlang:timestamp()的原因纯粹是为了简化对采用这种时间戳格式的现有代码的使用。可以使用erlang:system_time / 1以您选择的时间单位 + 更有效地检索当前Erlang系统时间 。 + The erlang:timestamp() BIF is equivalent to: + timestamp() -> + ErlangSystemTime = erlang:system_time(microsecond), + MegaSecs = ErlangSystemTime div 1000000000000, + Secs = ErlangSystemTime div 1000000 - MegaSecs*1000000, + MicroSecs = ErlangSystemTime rem 1000000, + {MegaSecs, Secs, MicroSecs}. + + +calendar 时间模块 -------》》》》》 + 模块总结 + 本地和世界时间,星期几,日期和时间转换。 + 描述 + 此模块提供本地和通用时间,星期几以及许多时间转换功能的计算。 + + 根据当前时区和夏令时进行调整时,时间是本地时间。当它反映的是经度为零的时间时,它是通用的,无需为夏时制进行任何调整。 + 世界标准时间(UTC)时间也称为格林威治标准时间(GMT)。 + + 此模块中的时间函数local_time / 0和 Universal_time / 0都返回日期和时间。这是因为日期和时间的单独功能可能导致日期/时间组合错开24小时。 + 如果其中一个功能在午夜之前调用,而另一个功能在午夜之后调用,则会发生这种情况。此问题也适用于Erlang BIF date / 0和time / 0, + 如果需要可靠的日期/时间戳,强烈建议不要使用它们。 + + 所有日期均符合公历。此历法由教皇格雷戈里十三世在1582年引入,从今年开始在所有天主教国家中使用。德国和荷兰的新教部分在1698年采用了它, + 英格兰随后在1752年采用了,俄国在1918年(根据格里高利历法,1917年10月的革命发生在11月)。 + + 此模块中的公历将回溯到0年。对于给定的日期,公历天数是指指定日期之前(包括该日期)的天数。同样,指定日期和时间的公历秒数是直至并包括指定日期和时间的秒数。 + + 要计算时间间隔之间的差异,请使用计算公历天或秒的功能。如果将纪元指定为本地时间,则必须将其转换为通用时间,以获取各纪元之间经过时间的正确值 + 。不建议使用功能time_difference / 2。 + + 一年中的一周存在不同的定义。该模块包含符合ISO 8601标准的一年中的一周实施。由于指定日期的星期数可以落在上一个,当前或下一年, + 因此指定年号和星期数很重要。函数iso_week_number / 0和iso_week_number / 1 返回年份和星期数的元组。 +calendar: + +date_to_gregorian_days/1 +date_to_gregorian_days/3 + 计算从0年开始到指定日期结束的公历天数。 + +datetime_to_gregorian_seconds/1 + 计算从年份0开始到指定的日期和时间的公历秒数。 + +gregorian_days_to_date/1 + 根据指定的公历天数计算日期。 +gregorian_seconds_to_datetime/1 + 根据指定的公历秒数计算日期和时间。 + +day_of_the_week/1 +day_of_the_week/3 + 从指定的Year,Month和 Day计算星期几 。将星期几返回为 1:星期一,2:星期二,依此类推。 + +is_leap_year/1 + 检查指定的年份是否为闰年。 + +iso_week_number/0 + 返回表示实际日期的ISO周编号的元组{Year,WeekNum}。要确定实际日期,请使用函数 local_time / 0。 +iso_week_number/1 + 返回表示指定日期的ISO周编号的元组{Year,WeekNum}。 + +last_day_of_the_month/2 + 计算一个月中的天数。 + +local_time/0 + 等效于 erlang:localtime() + +local_time_to_universal_time/1 %% 不推荐使用了 额豁 + 从本地时间转换为世界标准时间(UTC)。 DateTime1必须引用1970年1月1日之后的本地日期。 + 警告:不推荐使用此功能。请改用 local_time_to_universal_time_dst / 1 ,因为它可以提供更正确和完整的结果。 + 尤其是对于不存在的时间段,由于在切换到夏时制时会被跳过,因此此功能仍会返回结果。 +local_time_to_universal_time/2 + +local_time_to_universal_time_dst/1 + 从本地时间转换为世界标准时间(UTC)。 参数DateTime1必须引用1970年1月1日之后的本地日期。 + + 返回值是0、1或2个可能的UTC时间的列表: + + [] + 对于当地时间{Date1,Time1},在切换到夏令时时会跳过该时间段,因此没有相应的UTC,因为当地时间是非法的(从未发生过)。 + + [DstDateTimeUTC,DateTimeUTC] + 对于从夏令时开始重复的时段中的本地{Date1,Time1},存在两个对应的UTC;一个用于夏令时仍处于活动状态的时段的第一个实例,另一个用于第二个实例。 + + [DateTimeUTC] + 对于所有其他本地时间,仅存在一个对应的UTC。 + +now_to_datetime/1 % = now_to_universal_time/1 + 返回从erlang:timestamp / 0的返回值转换的通用协调时间(UTC) 。 + +now_to_local_time/1 + 返回从erlang:timestamp / 0的返回值转换的本地日期和时间 。 + +now_to_universal_time/1 + 返回从erlang:timestamp / 0的返回值转换的通用协调时间(UTC) 。 + +rfc3339_to_system_time/1 +rfc3339_to_system_time/2 + 将RFC 3339时间戳转换为系统时间。RFC 3339描述了RFC 3339时间戳的数据格式 。 + +seconds_to_daystime/1 + 将指定的秒数转换为天,小时,分钟和秒。时间始终是非负的,但是如果参数Seconds是,则 Days是负的 。 + +seconds_to_time/1 + 根据指定的秒数计算时间。 秒数必须小于每天的秒数(86400)。 + +system_time_to_local_time/2 + 将指定的系统时间转换为本地日期和时间。 TODO 优化此函数 + +system_time_to_universal_time/2 TODO 优化此函数 + 将指定的系统时间转换为通用日期和时间。 + +system_time_to_rfc3339/1 +system_time_to_rfc3339/2 + 将系统时间转换为RFC 3339时间戳。RFC 3339描述了RFC 3339时间戳的数据格式 。偏移量的数据格式也由RFC 3339描述。 + +time_difference/2 %% 改函数过时 不用 +time_to_seconds/1 + 返回自午夜到指定时间的秒数。 + +universal_time/0 + 等效于erlang:universaltime(). + +universal_time_to_local_time/1 + erlang:universaltime_to_localtime(DateTime). + +valid_date/1 +valid_date/3 + 此功能检查日期是否有效。 \ No newline at end of file diff --git a/src/timeDate/utTime.erl b/src/timeDate/utTime.erl new file mode 100644 index 0000000..2b86e2f --- /dev/null +++ b/src/timeDate/utTime.erl @@ -0,0 +1,667 @@ +-module(utTime). +-include("utTime.hrl"). + +-compile([export_all, nowarn_export_all]). + +-type year() :: non_neg_integer(). +-type month() :: 1..12. +-type day() :: 1..31. +-type hour() :: 0..23. +-type minute() :: 0..59. +-type second() :: 0..59. +-type date() :: {year(),month(),day()}. +-type time() :: {hour(),minute(),second()}. +-type datetime() :: {date(),time()}. +-type timestamp() :: non_neg_integer(). %% 时间戳 +-type week() :: 1..7. +-type weekCycle() :: 1..53. %% 一年最多53个周 +-type yearWeekCycle() :: {year(), weekCycle()}. + +-import(calendar, + [ + day_of_the_week/1 + , iso_week_number/1 + , date_to_gregorian_days/1 + ]). + +%% 当前的时间戳 秒 +-spec now() -> timestamp(). +now() -> + erlang:system_time(second). + +%% 当前的时间戳 毫秒 +-spec nowMs() -> timestamp(). +nowMs() -> + erlang:system_time(millisecond). + +%% 当前的日期 +-spec curDateTime() -> datetime(). +curDateTime() -> + erlang:localtime(). + +%% 当前的年月日 +-spec curDate() -> date(). +curDate() -> + erlang:date(). + +%% 当前的时分秒 +-spec curTime() -> time(). +curTime() -> + erlang:time(). + +%% 当前星期几 +-spec weekDay() -> week(). +weekDay() -> + calendar:day_of_the_week(erlang:date()). + +%% 计算Data是星期几 +-spec weekDay(Date :: date()) -> week(). +weekDay(Date) -> + calendar:day_of_the_week(Date). + +%% 计算 年 月 日 是星期几 +-spec weekDay(Year :: year(), Month :: month(), Day :: day()) -> week(). +weekDay(Year, Month, Day) -> + calendar:day_of_the_week(Year, Month, Day). + +%% 计算当前的星期周期 +-spec weekCycle() -> yearWeekCycle(). +weekCycle() -> + calendar:iso_week_number(erlang:date()). + +%% 计算 Date 的星期周期 +-spec weekCycle(Date :: date()) -> yearWeekCycle(). +weekCycle(Date) -> + calendar:iso_week_number(Date). + +%% 将秒单位的时间戳 转为本地 datetime() +-spec secToLocalTime(Sec :: timestamp()) -> datetime(). +secToLocalTime(Ses) -> + erlang:universaltime_to_localtime(erlang:posixtime_to_universaltime(Ses)). + +%% 将秒单位的时间戳 转为世界 datetime() +-spec secToUniversalTime(Sec :: timestamp()) -> datetime(). +secToUniversalTime(Ses) -> + erlang:posixtime_to_universaltime(Ses). + +%% 将本地的 datetime() 转为秒单位的时间戳 +-spec localTimeToSec(LocalDate :: datetime()) -> timestamp(). +localTimeToSec(LocalDate) -> + erlang:universaltime_to_posixtime(erlang:localtime_to_universaltime(LocalDate)). + +%% 将世界的 datetime() 转为秒单位的时间戳 +-spec universalTimeToSec(UniversalTime :: datetime()) -> timestamp(). +universalTimeToSec(UniversalTime) -> + erlang:universaltime_to_posixtime(UniversalTime). + +%% 获取本地时区与UTC时区 时间差 单位秒 由于某些时区存在夏令时 下面的计算在不同时候 可能会返回不同的值 所以并不能只计算一次 需要在每次用到的时候 重新计算 +-spec timeZoneDiff() -> timestamp(). +timeZoneDiff() -> + Local2001 = erlang:universaltime_to_localtime({{2001, 1, 1}, {0, 0, 0}}), + erlang:universaltime_to_posixtime(Local2001) - 978307200. + +%% 计算1970年到Sec 本地经过了多少天 +-spec countLDay(Sec :: timestamp()) -> integer(). +countLDay(Sec) -> + (Sec + timeZoneDiff()) div ?SECS_DAY. + +%% 计算1970年到Sec 世界经过了多少天 +-spec countUDay(Sec :: timestamp()) -> integer(). +countUDay(Sec) -> + Sec div ?SECS_DAY. + +%% 判断两个时间戳是否为本地的同一天 +-spec isSameLDay(Sec1 :: timestamp(), Sec2 :: timestamp()) -> boolean(). +isSameLDay(Sec1, Sec2) -> + TimeZoneDiff = timeZoneDiff(), + (Sec1 + TimeZoneDiff) div ?SECS_DAY =:= (Sec2 + TimeZoneDiff) div ?SECS_DAY. + +%% 判断两个时间戳是否为本地的同一天 +-spec isSameUDay(Sec1 :: timestamp(), Sec2 :: timestamp()) -> boolean(). +isSameUDay(Sec1, Sec2) -> + Sec1 div ?SECS_DAY =:= Sec2 div ?SECS_DAY. + +%% 计算1970年到Sec 本地经过了多少周 +-spec countLWeek(Sec :: timestamp()) -> integer(). +countLWeek(Sec) -> + (Sec + 259200 + timeZoneDiff()) div ?SECS_WEEK. + +%% 计算1970年到Sec 世界经过了多少周 +-spec countUWeek(Sec :: timestamp()) -> integer(). +countUWeek(Sec) -> + (Sec + 259200) div ?SECS_WEEK. + +%% 判断两个时间戳是否为本地的同一周 +-spec isSameLWeek(Sec1 :: timestamp(), Sec2 :: timestamp()) -> boolean(). +isSameLWeek(Sec1, Sec2) -> + TimeZoneDiff = timeZoneDiff(), + (Sec1 + 259200 + TimeZoneDiff) div ?SECS_WEEK =:= (Sec2 + 259200 + TimeZoneDiff) div ?SECS_WEEK. + +%% 判断两个时间戳是否为本地的同一周 +-spec isSameUWeek(Sec1 :: timestamp(), Sec2 :: timestamp()) -> boolean(). +isSameUWeek(Sec1, Sec2) -> + (Sec1 + 259200) div ?SECS_WEEK =:= (Sec2 + 259200) div ?SECS_WEEK. + +%% 判断两个时间戳是否为本地的同一月 +-spec isSameLMonth(Sec1 :: timestamp(), Sec2 :: timestamp()) -> boolean(). +isSameLMonth(Sec1, Sec2) -> + {{Year1, Month1, _Day1}, _Time1} = secToLocalTime(Sec1), + {{Year2, Month2, _Day2}, _Time2} = secToLocalTime(Sec2), + Month1 =:= Month2 andalso Year1 =:= Year2. + +%% 判断两个时间戳是否为世界的同一月 +-spec isSameUMonth(Sec1 :: timestamp(), Sec2 :: timestamp()) -> boolean(). +isSameUMonth(Sec1, Sec2) -> + {{Year1, Month1, _Day1}, _Time1} = secToUniversalTime(Sec1), + {{Year2, Month2, _Day2}, _Time2} = secToUniversalTime(Sec2), + Month1 =:= Month2 andalso Year1 =:= Year2. + +%% 计算1970年到Sec 本地经过了多少天 ZeroOffset为零点偏移时间 +-spec countLDay(Sec :: timestamp(), ZeroOffset :: timestamp()) -> integer(). +countLDay(Sec, ZeroOffset) -> + (Sec - ZeroOffset + timeZoneDiff()) div ?SECS_DAY. + +%% 计算1970年到Sec 世界经过了多少天 ZeroOffset为零点偏移时间 +-spec countUDay(Sec :: timestamp(), ZeroOffset :: timestamp()) -> integer(). +countUDay(Sec, ZeroOffset) -> + (Sec - ZeroOffset) div ?SECS_DAY. + +%% 判断两个时间戳是否为同一天 ZeroOffset为零点偏移时间 +-spec isSameLDay(Sec1 :: timestamp(), Sec2 :: timestamp(), ZeroOffset :: timestamp()) -> boolean(). +isSameLDay(Sec1, Sec2, ZeroOffset) -> + TimeZoneDiff = timeZoneDiff(), + (Sec1 - ZeroOffset + TimeZoneDiff) div ?SECS_DAY =:= (Sec2 - ZeroOffset + TimeZoneDiff) div ?SECS_DAY. + +%% 判断两个时间戳是否为同一天 ZeroOffset为零点偏移时间 +-spec isSameUDay(Sec1 :: timestamp(), Sec2 :: timestamp(), ZeroOffset :: timestamp()) -> boolean(). +isSameUDay(Sec1, Sec2, ZeroOffset) -> + (Sec1 - ZeroOffset) div ?SECS_DAY =:= (Sec2 - ZeroOffset) div ?SECS_DAY. + +%% 计算1970年到Sec 本地经过了多少周 ZeroOffset为零点偏移时间 +-spec countLWeek(Sec :: timestamp(), ZeroOffset :: timestamp()) -> integer(). +countLWeek(Sec, ZeroOffset) -> + (Sec - ZeroOffset + 259200 + timeZoneDiff()) div ?SECS_WEEK. + +%% 计算1970年到Sec 世界经过了多少周 ZeroOffset为零点偏移时间 +-spec countUWeek(Sec :: timestamp(), ZeroOffset :: timestamp()) -> integer(). +countUWeek(Sec, ZeroOffset) -> + (Sec - ZeroOffset + 259200) div ?SECS_WEEK. + +%% 判断两个时间戳是否为同一周 ZeroOffset为零点偏移时间 +-spec isSameLWeek(Sec1 :: timestamp(), Sec2 :: timestamp(), ZeroOffset :: timestamp()) -> boolean(). +isSameLWeek(Sec1, Sec2, ZeroOffset) -> + TimeZoneDiff = timeZoneDiff(), + (Sec1 - ZeroOffset + 259200 + TimeZoneDiff) div ?SECS_WEEK =:= (Sec2 - ZeroOffset + 259200 + TimeZoneDiff) div ?SECS_WEEK. + +%% 判断两个时间戳是否为同一周 ZeroOffset为零点偏移时间 +-spec isSameUWeek(Sec1 :: timestamp(), Sec2 :: timestamp(), ZeroOffset :: timestamp()) -> boolean(). +isSameUWeek(Sec1, Sec2, ZeroOffset) -> + (Sec1 - ZeroOffset + 259200) div ?SECS_WEEK =:= (Sec2 - ZeroOffset + 259200) div ?SECS_WEEK. + +%% 判断两个时间戳是否为本地的同一月 ZeroOffset为零点偏移时间 +-spec isSameLMonth(Sec1 :: timestamp(), Sec2 :: timestamp(), ZeroOffset :: timestamp()) -> boolean(). +isSameLMonth(Sec1, Sec2, ZeroOffset) -> + {{Year1, Month1, _Day1}, _Time1} = secToLocalTime(Sec1 - ZeroOffset), + {{Year2, Month2, _Day2}, _Time2} = secToLocalTime(Sec2 - ZeroOffset), + Month1 =:= Month2 andalso Year1 =:= Year2. + +%% 判断两个时间戳是否为世界的同一月 ZeroOffset为零点偏移时间 +-spec isSameUMonth(Sec1 :: timestamp(), Sec2 :: timestamp(), ZeroOffset :: timestamp()) -> boolean(). +isSameUMonth(Sec1, Sec2, ZeroOffset) -> + {{Year1, Month1, _Day1}, _Time1} = secToUniversalTime(Sec1 - ZeroOffset), + {{Year2, Month2, _Day2}, _Time2} = secToUniversalTime(Sec2 - ZeroOffset), + Month1 =:= Month2 andalso Year1 =:= Year2. + +%% 当前小时开始时间戳 +-spec hourBegin() -> timestamp(). +hourBegin() -> + Sec = erlang:system_time(second), + Sec - Sec rem ?SECS_HOUR. + +%% Sec所在小时开始时间戳 +-spec hourBegin(Sec :: timestamp()) -> timestamp(). +hourBegin(Sec) -> + Sec - Sec rem ?SECS_HOUR. + +%% 当前小时结束时间戳 +-spec hourEnd() -> timestamp(). +hourEnd() -> + Sec = erlang:system_time(second), + Sec - Sec rem ?SECS_HOUR + ?SECS_HOUR. + +%% Sec所在小时结束时间戳 +-spec hourEnd(Sec :: timestamp()) -> timestamp(). +hourEnd(Sec) -> + Sec - Sec rem ?SECS_HOUR + ?SECS_HOUR. + +%% 本地当前天开始时间戳 +-spec dayLBegin() -> timestamp(). +dayLBegin() -> + Sec = erlang:system_time(second), + Sec - (Sec + timeZoneDiff()) rem ?SECS_DAY. + +%% 本地Sec所在天开始时间戳 +-spec dayLBegin(Sec :: timestamp()) -> timestamp(). +dayLBegin(Sec) -> + Sec - (Sec + timeZoneDiff()) rem ?SECS_DAY. + +%% 世界Sec所在天开始时间戳 +-spec dayUBegin() -> timestamp(). +dayUBegin() -> + Sec = erlang:system_time(second), + Sec - Sec rem ?SECS_DAY. + +%% 世界Sec所在天开始时间戳 +-spec dayUBegin(Sec :: timestamp()) -> timestamp(). +dayUBegin(Sec) -> + Sec - Sec rem ?SECS_DAY. + +%% 本地当前天结束时间戳 +-spec dayLEnd() -> timestamp(). +dayLEnd() -> + Sec = erlang:system_time(second), + Sec - (Sec + timeZoneDiff()) rem ?SECS_DAY + ?SECS_DAY. + +%% 本地Sec所在天结束时间戳 +-spec dayLEnd(Sec :: timestamp()) -> timestamp(). +dayLEnd(Sec) -> + Sec - (Sec + timeZoneDiff()) rem ?SECS_DAY + ?SECS_DAY. + +%% 世界当前天结束时间戳 +-spec dayUEnd() -> timestamp(). +dayUEnd() -> + Sec = erlang:system_time(second), + Sec - Sec rem ?SECS_DAY + ?SECS_DAY. + +%% 世界Sec所在天结束时间戳 +-spec dayUEnd(Sec :: timestamp()) -> timestamp(). +dayUEnd(Sec) -> + Sec - Sec rem ?SECS_DAY + ?SECS_DAY. + +%% 本地当前天开始结束时间戳 +-spec dayLBeginEnd() -> timestamp(). +dayLBeginEnd() -> + Sec = erlang:system_time(second), + Begin = Sec - (Sec + timeZoneDiff()) rem ?SECS_DAY, + {Begin, Begin + ?SECS_DAY}. + +%% 本地Sec所在天开始结束时间戳 +-spec dayLBeginEnd(Sec :: timestamp()) -> timestamp(). +dayLBeginEnd(Sec) -> + Begin = Sec - (Sec + timeZoneDiff()) rem ?SECS_DAY, + {Begin, Begin + ?SECS_DAY}. + +%% 世界当前天开始结束时间戳 +-spec dayUBeginEnd() -> timestamp(). +dayUBeginEnd() -> + Sec = erlang:system_time(second), + Begin = Sec - Sec rem ?SECS_DAY, + {Begin, Begin + ?SECS_DAY}. + +%% 世界Sec所在天开始结束时间戳 +-spec dayUBeginEnd(Sec :: timestamp()) -> timestamp(). +dayUBeginEnd(Sec) -> + Begin = Sec - Sec rem ?SECS_DAY, + {Begin, Begin + ?SECS_DAY}. + +%% 本地当前周开始时间戳 +-spec weekLBegin() -> timestamp(). +weekLBegin() -> + Sec = erlang:system_time(second), + Sec - (Sec - 345600 + timeZoneDiff()) rem ?SECS_WEEK. + +%% 本地Sec所在周开始时间戳 +-spec weekLBegin(Sec :: timestamp()) -> timestamp(). +weekLBegin(Sec) -> + Sec - (Sec - 345600 + timeZoneDiff()) rem ?SECS_WEEK. + +%% 世界当前周的开始时间戳 +-spec weekUBegin() -> timestamp(). +weekUBegin() -> + Sec = erlang:system_time(second), + Sec - (Sec - 345600) rem ?SECS_WEEK. + +%% 世界Sec所在周的开始时间戳 +-spec weekUBegin(Sec :: timestamp()) -> timestamp(). +weekUBegin(Sec) -> + Sec - (Sec - 345600) rem ?SECS_WEEK. + +%% 本地当前周的结束时间戳 +-spec weekLEnd() -> timestamp(). +weekLEnd() -> + Sec = erlang:system_time(second), + Sec - (Sec - 345600 + timeZoneDiff()) rem ?SECS_WEEK + ?SECS_WEEK. + +%% 本地Sec所在周的结束时间戳 +-spec weekLEnd(Sec :: timestamp()) -> timestamp(). +weekLEnd(Sec) -> + Sec - (Sec - 345600 + timeZoneDiff()) rem ?SECS_WEEK + ?SECS_WEEK. + +%% 世界当前周的开始时间戳 +-spec weekUEnd() -> timestamp(). +weekUEnd() -> + Sec = erlang:system_time(second), + Sec - (Sec - 345600) rem ?SECS_WEEK + ?SECS_WEEK. + +%% 世界Sec所在周的结束时间戳 +-spec weekUEnd(Sec :: timestamp()) -> timestamp(). +weekUEnd(Sec) -> + Sec - (Sec - 345600) rem ?SECS_WEEK + ?SECS_WEEK. + +%% 本地当前周的开始结束时间戳 +-spec weekLBeginEnd() -> timestamp(). +weekLBeginEnd() -> + Sec = erlang:system_time(second), + Begin = Sec - (Sec - 345600 + timeZoneDiff()) rem ?SECS_WEEK, + {Begin, Begin + ?SECS_WEEK}. + +%% 本地Sec所在周的开始结束时间戳 +-spec weekLBeginEnd(Sec :: timestamp()) -> timestamp(). +weekLBeginEnd(Sec) -> + Begin = Sec - (Sec - 345600 + timeZoneDiff()) rem ?SECS_WEEK, + {Begin, Begin + ?SECS_WEEK}. + +%% 世界当前周的开始结束时间戳 +-spec weekUBeginEnd() -> timestamp(). +weekUBeginEnd() -> + Sec = erlang:system_time(second), + Begin = Sec - (Sec - 345600) rem ?SECS_WEEK, + {Begin, Begin + ?SECS_WEEK}. + +%% 世界Sec所在周的开始结束时间戳 +-spec weekUBeginEnd(Sec :: timestamp()) -> timestamp(). +weekUBeginEnd(Sec) -> + Begin = Sec - (Sec - 345600) rem ?SECS_WEEK, + {Begin, Begin + ?SECS_WEEK}. + +%% 本地当前月的开始时间戳 +-spec monthLBegin() -> timestamp(). +monthLBegin() -> + Sec = erlang:system_time(second), + {{Year, Month, _Day}, _Time} = secToLocalTime(Sec), + MonthStartDateTime = {{Year, Month, 1}, {0, 0, 0}}, + localTimeToSec(MonthStartDateTime). + +%% 本地Sec所在月的开始时间戳 +-spec monthLBegin(Sec :: timestamp()) -> timestamp(). +monthLBegin(Sec) -> + {{Year, Month, _Day}, _Time} = secToLocalTime(Sec), + MonthStartDateTime = {{Year, Month, 1}, {0, 0, 0}}, + localTimeToSec(MonthStartDateTime). + +%% 世界当前月的开始时间戳 +-spec monthUBegin() -> timestamp(). +monthUBegin() -> + Sec = erlang:system_time(second), + {{Year, Month, _Day}, _Time} = erlang:posixtime_to_universaltime(Sec), + MonthStartDateTime = {{Year, Month, 1}, {0, 0, 0}}, + erlang:universaltime_to_posixtime(MonthStartDateTime). + +%% 世界Sec所在月的开始时间戳 +-spec monthUBegin(Sec :: timestamp()) -> timestamp(). +monthUBegin(Sec) -> + {{Year, Month, _Day}, _Time} = erlang:posixtime_to_universaltime(Sec), + MonthStartDateTime = {{Year, Month, 1}, {0, 0, 0}}, + erlang:universaltime_to_posixtime(MonthStartDateTime). + +%% 本地当前月的结束时间戳 +-spec monthLEnd() -> timestamp(). +monthLEnd() -> + Sec = erlang:system_time(second), + {{Year, Month, _Day}, _Time} = secToLocalTime(Sec), + MonthDay = monthDay(Year, Month), + MonthEndDateTime = {{Year, Month, MonthDay}, {23, 59, 59}}, + localTimeToSec(MonthEndDateTime). + +%% 本地Sec所在月的结束时间戳 +-spec monthLEnd(Sec :: timestamp()) -> timestamp(). +monthLEnd(Sec) -> + {{Year, Month, _Day}, _Time} = secToLocalTime(Sec), + MonthDay = monthDay(Year, Month), + MonthEndDateTime = {{Year, Month, MonthDay}, {23, 59, 59}}, + localTimeToSec(MonthEndDateTime). + +%% 世界当前周的结束时间戳 +-spec monthUEnd() -> timestamp(). +monthUEnd() -> + Sec = erlang:system_time(second), + {{Year, Month, _Day}, _Time} = erlang:posixtime_to_universaltime(Sec), + MonthDay = monthDay(Year, Month), + MonthEndDateTime = {{Year, Month, MonthDay}, {23, 59, 59}}, + erlang:universaltime_to_posixtime(MonthEndDateTime). + +%% 世界Sec所在月的结束时间戳 +-spec monthUEnd(Sec :: timestamp()) -> timestamp(). +monthUEnd(Sec) -> + {{Year, Month, _Day}, _Time} = erlang:posixtime_to_universaltime(Sec), + MonthDay = monthDay(Year, Month), + MonthEndDateTime = {{Year, Month, MonthDay}, {23, 59, 59}}, + erlang:universaltime_to_posixtime(MonthEndDateTime). + +%% 闰年判断函数 +-spec isLeapYear(Yesr :: year()) -> boolean(). +isLeapYear(Year) -> + (Year rem 4 =:= 0 andalso Year rem 100 =/= 0) orelse (Year rem 400 =:= 0). + +%% 根据 年 月 返回对应月的天数 +-spec monthDay(year(), month()) -> timestamp(). +monthDay(_, 4) -> 30; +monthDay(_, 6) -> 30; +monthDay(_, 9) -> 30; +monthDay(_, 11) -> 30; +monthDay(Y, 2) -> + case isLeapYear(Y) of + true -> 29; + _ -> 28 + end; +monthDay(_, _) -> + 31. + +%% 根据年月 返回月的总秒数 +-spec monthSecs(year(), month()) -> timestamp(). +monthSecs(_, 4) -> 2592000; +monthSecs(_, 6) -> 2592000; +monthSecs(_, 9) -> 2592000; +monthSecs(_, 11) -> 2592000; +monthSecs(Y, 2) -> + case isLeapYear(Y) of + true -> 2505600; + _ -> 2419200 + end; +monthSecs(_, _) -> + 2678400. + +%% 本地当前月的开始结束时间戳 +-spec monthLBeginEnd() -> timestamp(). +monthLBeginEnd() -> + Sec = erlang:system_time(second), + {{Year, Month, _Day}, _Time} = secToLocalTime(Sec), + MonthStartDateTime = {{Year, Month, 1}, {0, 0, 0}}, + Begin = localTimeToSec(MonthStartDateTime), + {Begin, Begin + monthSecs(Year, Month)}. + +%% 本地Sec所在月的开始结束时间戳 +-spec monthLBeginEnd(Sec :: timestamp()) -> timestamp(). +monthLBeginEnd(Sec) -> + {{Year, Month, _Day}, _Time} = secToLocalTime(Sec), + MonthStartDateTime = {{Year, Month, 1}, {0, 0, 0}}, + Begin = localTimeToSec(MonthStartDateTime), + {Begin, Begin + monthSecs(Year, Month)}. + +%% 世界当前月的开始结束时间戳 +-spec monthUBeginEnd() -> timestamp(). +monthUBeginEnd() -> + Sec = erlang:system_time(second), + {{Year, Month, _Day}, _Time} = erlang:posixtime_to_universaltime(Sec), + MonthStartDateTime = {{Year, Month, 1}, {0, 0, 0}}, + Begin = erlang:universaltime_to_posixtime(MonthStartDateTime), + {Begin, Begin + monthSecs(Year, Month)}. + +%% 世界Sec所在月的开始结束时间戳 +-spec monthUBeginEnd(Sec :: timestamp()) -> timestamp(). +monthUBeginEnd(Sec) -> + {{Year, Month, _Day}, _Time} = erlang:posixtime_to_universaltime(Sec), + MonthStartDateTime = {{Year, Month, 1}, {0, 0, 0}}, + Begin = erlang:universaltime_to_posixtime(MonthStartDateTime), + {Begin, Begin + monthSecs(Year, Month)}. + +%% 星期名字缩写 +-spec sWeekName(week()) -> string(). +sWeekName(1) -> <<"Mon">>; +sWeekName(2) -> <<"Tue">>; +sWeekName(3) -> <<"Wed">>; +sWeekName(4) -> <<"Thu">>; +sWeekName(5) -> <<"Fri">>; +sWeekName(6) -> <<"Sat">>; +sWeekName(7) -> <<"Sun">>. + +%% 星期名字全称 +-spec lWeekName(week()) -> string(). +lWeekName(1) -> <<"Monday">>; +lWeekName(2) -> <<"Tuesday">>; +lWeekName(3) -> <<"Wednesday">>; +lWeekName(4) -> <<"Thursday">>; +lWeekName(5) -> <<"Friday">>; +lWeekName(6) -> <<"Saturday">>; +lWeekName(7) -> <<"Sunday">>. + +%% 月份名称缩写 +-spec sMonthName(month()) -> string(). +sMonthName(1) -> <<"Jan">>; +sMonthName(2) -> <<"Feb">>; +sMonthName(3) -> <<"Mar">>; +sMonthName(4) -> <<"Apr">>; +sMonthName(5) -> <<"May">>; +sMonthName(6) -> <<"Jun">>; +sMonthName(7) -> <<"Jul">>; +sMonthName(8) -> <<"Aug">>; +sMonthName(9) -> <<"Sep">>; +sMonthName(10) -> <<"Oct">>; +sMonthName(11) -> <<"Nov">>; +sMonthName(12) -> <<"Dec">>. + +%% 月份名称全称 +-spec lMonthName(month()) -> string(). +lMonthName(1) -> <<"January">>; +lMonthName(2) -> <<"February">>; +lMonthName(3) -> <<"March">>; +lMonthName(4) -> <<"April">>; +lMonthName(5) -> <<"May">>; +lMonthName(6) -> <<"June">>; +lMonthName(7) -> <<"July">>; +lMonthName(8) -> <<"August">>; +lMonthName(9) -> <<"September">>; +lMonthName(10) -> <<"October">>; +lMonthName(11) -> <<"November">>; +lMonthName(12) -> <<"December">>. + +%% 年月日的数字version +-spec dateNum() -> integer(). +dateNum() -> + {Year, Month, Day} = erlang:date(), + Year * 10000 + Month * 100 + Day. + +%% 年月日的数字version +-spec dateNum(date()) -> integer(). +dateNum({Year, Month, Day}) -> + Year * 10000 + Month * 100 + Day. + +%% 年月日的数字version +-spec dateNum(Year :: year(), Month :: month(), Day :: day()) -> integer(). +dateNum(Year, Month, Day) -> + Year * 10000 + Month * 100 + Day. + +%% 秒转为天数 和 time() +-spec secToDayTime(Secs :: timestamp()) -> {Day :: integer(), Time :: time()}. +secToDayTime(Secs) -> + Days0 = Secs div ?SECS_DAY, + Secs0 = Secs rem ?SECS_DAY, + Hour = Secs0 div ?SECS_HOUR, + Secs1 = Secs0 rem ?SECS_HOUR, + Minute = Secs1 div ?SECS_MIN, + Second = Secs1 rem ?SECS_MIN, + {Days0, {Hour, Minute, Second}}. + +%% 计算两个本地datetime() 时间差 单位 秒 +-spec diffLDateTimeSec(datetime(), datetime()) -> timestamp(). +diffLDateTimeSec(DateTime1, DateTime2) -> + Secs = localTimeToSec(DateTime1) - localTimeToSec(DateTime2), + erlang:abs(Secs). + +%% 计算两个世界datetime() 时间差 单位 秒 +-spec diffUDateTimeSec(datetime(), datetime()) -> timestamp(). +diffUDateTimeSec(DateTime1, DateTime2) -> + Secs = universalTimeToSec(DateTime1) - universalTimeToSec(DateTime2), + erlang:abs(Secs). + +%% 计算两个本地datetime() 时间差 单位 daytime() +-spec diffLDateTimeDayTime(datetime(), datetime()) -> timestamp(). +diffLDateTimeDayTime(DateTime1, DateTime2) -> + Secs = localTimeToSec(DateTime1) - localTimeToSec(DateTime2), + secToDayTime(erlang:abs(Secs)). + +%% 计算两个世界datetime() 时间差 单位 daytime() +-spec diffUDateTimeDayTime(datetime(), datetime()) -> timestamp(). +diffUDateTimeDayTime(DateTime1, DateTime2) -> + Secs = universalTimeToSec(DateTime1) - universalTimeToSec(DateTime2), + secToDayTime(erlang:abs(Secs)). + +%% 计算两个秒单位的 时间戳 的时间差 单位 daytime() +-spec diffSecs(timestamp(), timestamp()) -> timestamp(). +diffSecs(Sec1, Sec2) -> + secToDayTime(erlang:abs(Sec1 - Sec2)). + +%% 转换 time() 为 Sec +-spec timeToSecs(time()) -> timestamp(). +timeToSecs({H, M, S}) -> + H * ?SECS_HOUR + M * ?SECS_MIN + S. + +%% 计算 Date为该年的哪一天 +-spec daysInYear(date()) -> integer(). +daysInYear({Y, _, _} = Date) -> + date_to_gregorian_days(Date) - date_to_gregorian_days({Y, 1, 1}). + +-spec dateToStr(date()) -> string(). +dateToStr({Year, Month, Day}) -> + S = io_lib:format("~B_~2.10.0B_~2.10.0B", [Year, Month, Day]), + lists:flatten(S). + +-spec dateToStr(year(), month(), day()) -> string(). +dateToStr(Year, Month, Day) -> + S = io_lib:format("~B_~2.10.0B_~2.10.0B", [Year, Month, Day]), + lists:flatten(S). + +-spec dateToStr(date(), string()) -> string(). +dateToStr({Year, Month, Day}, Separator) -> + S = io_lib:format("~B~w~2.10.0B~w~2.10.0B", [Year, Separator, Month, Separator, Day]), + lists:flatten(S). + +-spec dateToStr(year(), month(), day(), string()) -> string(). +dateToStr(Year, Month, Day, Separator) -> + S = io_lib:format("~B~w~2.10.0B~w~2.10.0B", [Year, Separator, Month, Separator, Day]), + lists:flatten(S). + +-spec timeToStr(time()) -> string(). +timeToStr({Hour, Minute, Second}) -> + S = io_lib:format("~B:~2.10.0B:~2.10.0B", [Hour, Minute, Second]), + lists:flatten(S). + +-spec timeToStr(hour(), minute(), second()) -> string(). +timeToStr(Hour, Minute, Second) -> + S = io_lib:format("~B:~2.10.0B:~2.10.0B", [Hour, Minute, Second]), + lists:flatten(S). + +-spec timeToStr(time(), string()) -> string(). +timeToStr({Hour, Minute, Second}, Separator) -> + S = io_lib:format("~B~w~2.10.0B~w~2.10.0B", [Hour, Separator, Minute, Separator, Second]), + lists:flatten(S). + +-spec timeToStr(hour(), minute(), second(), string()) -> string(). +timeToStr(Hour, Minute, Second, Separator) -> + S = io_lib:format("~B~w~2.10.0B~w~2.10.0B", [Hour, Separator, Minute, Separator, Second]), + lists:flatten(S). + +-spec dateTimeStr(datetime()) -> string(). +dateTimeStr({{Year, Month, Day}, {Hour, Minute, Second}}) -> + S = io_lib:format("~B_~2.10.0B_~2.10.0B ~B:~2.10.0B:~2.10.0B", [Year, Month, Day, Hour, Minute, Second]), + lists:flatten(S). \ No newline at end of file diff --git a/src/uuidMd5/utMd5.erl b/src/uuidMd5/utMd5.erl new file mode 100644 index 0000000..865ea3a --- /dev/null +++ b/src/uuidMd5/utMd5.erl @@ -0,0 +1,32 @@ +-module(utMd5). + +-compile([export_all, nowarn_export_all]). + +-spec getMd5(Str :: iodata()) -> binary(). +getMd5(Str) -> + erlang:md5(Str). + +-spec getMd5Hex(Str :: iodata()) -> string(). +getMd5Hex(Str) -> + utHex:binaryToHex(erlang:md5(Str)). + +-spec getMd5HexBin(Str :: iodata()) -> binary(). +getMd5HexBin(Str) -> + utHex:binaryToHexBin(erlang:md5(Str)). + +-spec(md5BinToHex(Md5Bin :: binary()) -> string()). +md5BinToHex(Md5Bin) -> + utHex:binaryToHex(Md5Bin). + +-spec(md5BinToHexBin(Md5Bin :: binary()) -> binary()). +md5BinToHexBin(Md5Bin) -> + utHex:binaryToHexBin(Md5Bin). + +-spec(hexToMd5Bin(Md5Hex :: string()) -> binary()). +hexToMd5Bin(Md5Hex) -> + list_to_binary(utHex:hexToBinary(Md5Hex)). + +-spec(hexBinToMd5Bin(Md5HexBin :: binary()) -> binary()). +hexBinToMd5Bin(Md5HexBin) -> + utHex:hexBinToBinary(Md5HexBin). + diff --git a/src/uuidMd5/utUuid.erl b/src/uuidMd5/utUuid.erl new file mode 100644 index 0000000..84851ce --- /dev/null +++ b/src/uuidMd5/utUuid.erl @@ -0,0 +1,26 @@ +-module(utUuid). + +-compile([export_all, nowarn_export_all]). + +-spec randStr(integer()) -> string(). +randStr(Length) -> + [ + begin + Char = 47 + rand:uniform(75), + if + Char =< 57 -> Char; + Char =< 59 -> 58 - rand:uniform(10); + Char =< 64 -> 64 + rand:uniform(26); + Char =< 90 -> Char; + Char =< 96 -> 96 + rand:uniform(26); + true -> Char + end + end || _ <- lists:seq(1, Length)]. + +-spec uuid() -> binary. +uuid() -> + erlang:md5(term_to_binary({erlang:system_time(nanosecond), rand:uniform(134217727), make_ref()})). + +-spec uuidHex() -> binary. +uuidHex() -> + utMd5:getMd5Hex(term_to_binary({erlang:system_time(nanosecond), rand:uniform(134217727), make_ref()})).