erlang:now()在v18中已弃用,最佳转换是什么

时间:2015-12-01 14:48:59

标签: elixir

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

它完成了这项工作,但我觉得这不是最好的方法。

有什么建议吗?

5 个答案:

答案 0 :(得分:7)

答案 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()

检查一下: http://www.erlang.org/doc/man/erlang.html#timestamp-0

答案 4 :(得分:1)

试试这个:

os:timestamp()

,可在v17和v18中找到。

另请参阅:http://www.erlang.org/doc/man/os.html