在MongoDB驱动程序的包中,我需要一个函数来生成唯一的文档ID.
此函数使用:erlang.now()
v18中不推荐使用的函数
我寻求如何迁移的帮助,但没有成功.
我的实际代码(缩短):
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
它完成了这项工作,但我觉得这不是最好的方法.
有什么建议吗?
这已经在"Erlang中的时间和时间校正"文档中以及"Time Youes On"后记中涵盖了精彩的"Learn You Some Erlang"一书中.
要同时支持OTP 17和18(及更高版本),您需要在编译时检测OTP版本.以下是lftpc项目的rebar.config示例:
{erl_opts, [ {platform_define, "(?=^[0-9]+)(?!^17$)", time_correction} ]}.
这种正则表达式检查有效,因为OTP 17的发布标记了语义版本控制的使用(或接近它),因此任何小于OTP 17的版本号都以R开头(如R16).
然后,在您的Erlang代码中,您可以执行以下操作:
-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中为jose项目定义:
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
该erlc_options
可以通过为项目(类似于你在你的问题中提到的解决方案)的Erlang或药剂代码引用:
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