Erlang: now () deprecated in v18, what's the best transition

In the package for the MongoDB driver, I needed a function to create a unique document identifier.

This function uses :erlang.now() , which is deprecated in v18

I am looking for help in how to tolerate, but without success.

My actual code (abbreviated):

 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 

I came up with the best:

 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 

He does the job, but I do not think this is the best way.

Any suggestion?

+7
elixir
source share
5 answers

To support OTP 17 and 18 (and later) at the same time, you will need to detect the OTP version at compile time. The following is an example from rebar.config for the lftpc project :

 {erl_opts, [ {platform_define, "(?=^[0-9]+)(?!^17$)", time_correction} ]}. 

This regular expression check works because the release of OTP 17 has indicated the use of a semantic version (or close to it), so anything smaller than OTP 17 has a version number starting with R (for example, R16).

Then in Erlang code you can do something like 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. 

If you are using a mix, you can define erlc_options , as is done in 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 

erlc_options can be referenced in the Erlang or Elixir code for the project (similar to the solution mentioned in your question):

 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 
+6
source share

This is already described in the documentation "Time Correction of Erlang Time" , as well as in "Time is Running" "postscript in the wonderful book" Find out what you, Erlang " .

+7
source share

If erlang:now() deprecated but not removed in Erlang 18, I would leave the code alone.

This is my reasoning: if you create new code, build it for Erlang 18 and later and use erlang:timestamp() . That is, if you create new code, will you need it so that it can work on both Erlang 17 and Erlang 18? Most likely, if this is new code, you can simply indicate that it only works on 18. And if you support the code and erlang:now() still works at 18, then what is the problem?

Remember that obsolete is not the same as deleted. It just means that you should avoid using it for a new job.

+2
source share

Try the following:

 erlang:timestamp() 

which is an alternative to erlang: now () in erlang 18

check this out: http://www.erlang.org/doc/man/erlang.html#timestamp-0

+1
source share

Try the following:

 os:timestamp() 

which is available for both v17 and v18.

See also: http://www.erlang.org/doc/man/os.html

+1
source share

All Articles