在MongoDB driver的包中,我需要一个函数来生成唯一的文档ID。
此函数使用v18中弃用的:erlang.now()
我寻求有关如何迁移的帮助,但没有成功。
我的实际代码(缩短):
defmodule MyModule_v17 do
use Bitwise, only_operators: true
def gen_trans_prefix do
{gs, s, ms} = :erlang.now
(gs * 1000000000000 + s * 1000000 + ms) &&& 281474976710655
end
end
我想出的最好:
defmodule MyModule_v18 do
use Bitwise, only_operators: true
Kernel.if Keyword.get(:erlang.module_info, :exports) |> Enum.any?(fn({:system_time, 1}) -> true; (_) -> false end) do
def gen_trans_prefix do
:erlang.system_time(:micro_seconds) &&& 281474976710655
end
else
def gen_trans_prefix do
{gs, s, ms} = :erlang.now
(gs * 1000000000000 + s * 1000000 + ms) &&& 281474976710655
end
end
end
它完成了这项工作,但我觉得这不是最好的方法。
有什么建议吗?
答案 0 :(得分:7)
"Time and Time Correction in Erlang" documentation以及"Time Goes On" postscript中的"Learn You Some Erlang" book已经涵盖了这一点。
答案 1 :(得分:5)
要同时支持OTP 17和18(及更高版本),您需要在编译时检测OTP版本。以下是rebar.config for the lftpc project:
中的示例{erl_opts, [
{platform_define, "(?=^[0-9]+)(?!^17$)", time_correction}
]}.
此正则表达式检查有效,因为OTP 17的发布标记了semantic versioning(或接近它)的使用,因此任何小于OTP 17的版本号都以R开头(如R16)。 / p>
然后,在您的Erlang代码中,您可以执行this:
之类的操作-ifdef(time_correction).
gen_trans_prefix() ->
{GS, S, MS} = erlang:timestamp(),
(GS * 1000000000000 + S * 1000000 + MS) band 281474976710655.
-else.
gen_trans_prefix() ->
{GS, S, MS} = erlang:now(),
(GS * 1000000000000 + S * 1000000 + MS) band 281474976710655.
-endif.
如果您正在使用mix,则可以在erlc_options
中定义mix.exs for the jose project:
def erlc_options do
extra_options = try do
case :erlang.list_to_integer(:erlang.system_info(:otp_release)) do
v when v >= 18 ->
[{:d, :time_correction}]
_ ->
[]
end
catch
_ ->
[]
end
extra_options
end
项目的Erlang或Elixir代码可以引用erlc_options
(类似于您在问题中提到的解决方案):
defmodule MyModule do
use Bitwise, only_operators: true
if Enum.member?(Mix.Project.get!.project[:erlc_options] || [], {:d, :time_correction}) do
def gen_trans_prefix do
{gs, s, ms} = :erlang.timestamp
(gs * 1000000000000 + s * 1000000 + ms) &&& 281474976710655
end
else
def gen_trans_prefix do
{gs, s, ms} = :erlang.now
(gs * 1000000000000 + s * 1000000 + ms) &&& 281474976710655
end
end
end
答案 2 :(得分:2)
如果在Erlang 18中erlang:now()
已弃用但已删除,那么我将单独留下代码。
这是我的理由:如果您构建新代码,请为Erlang 18及更高版本构建它并使用erlang:timestamp()
。也就是说,如果你构建新的代码,你需要它能够在Erlang 17和Erlang 18上运行吗?如果它是新的代码,你只能规定它只能在18上运行。如果你正在维护代码并且erlang:now()
仍在18中工作,那么可能是什么'这个问题?
请记住,已弃用与已删除不同。这只是意味着你应该避免将它用于新工作。
答案 3 :(得分:1)
试试这个:
erlang:timestamp()
这是erlang的替代方法:在erlang 18中的now()
答案 4 :(得分:1)