Packages
timex
1.0.0-rc2
3.7.13
3.7.12
3.7.11
3.7.9
3.7.8
3.7.7
3.7.6
3.7.5
3.7.3
3.7.2
3.7.1
3.7.0
3.6.4
3.6.3
3.6.2
retired
3.6.1
3.6.0
3.5.0
3.4.2
3.4.1
3.3.0
3.2.2
3.2.1
3.2.0
3.1.25
retired
3.1.24
3.1.23
3.1.22
3.1.21
3.1.20
3.1.19
3.1.18
3.1.17
3.1.16
3.1.15
3.1.13
3.1.12
3.1.11
3.1.10
3.1.9
3.1.8
3.1.7
3.1.6
3.1.5
3.1.4
3.1.3
3.1.2
3.1.1
3.1.0
3.0.8
3.0.7
3.0.6
3.0.5
3.0.4
3.0.3
3.0.2
3.0.1
3.0.0
2.2.1
2.1.6
2.1.5
2.1.4
2.1.3
2.1.2
2.1.1
2.1.0
2.0.0
1.0.2
1.0.1
1.0.0
1.0.0-rc4
1.0.0-rc3
1.0.0-rc2
1.0.0-rc1
1.0.0-pre
0.19.5
0.19.4
0.19.3
0.19.2
0.19.1
0.19.0
0.18.2
0.18.1
0.18.0
0.17.0
0.16.2
0.16.1
0.16.0
0.15.0
0.14.3
0.14.2
0.14.1
0.14.0
0.13.5
0.13.4
0.13.3
0.13.2
0.13.1
0.13.0
0.12.9
0.12.8
0.12.7
0.12.6
0.12.5
0.12.4
0.12.3
0.12.2
0.12.1
0.12.0
0.11.0
0.10.2
0.10.1
0.10.0
0.9.0
0.8.0
0.7.1
0.6.0
0.5.0
0.4.8
0.4.7
0.4.6
Timex is a rich, comprehensive Date/Time library for Elixir projects, with full timezone support via the :tzdata package. If you need to manipulate dates, times, datetimes, timestamps, etc., then Timex is for you!
Current section
Files
Jump to
Current section
Files
lib/utils/utils.ex
defmodule Timex.Utils do
@moduledoc false
@doc """
Determines the current version of OTP running this node. The result is
cached for fast lookups in performance-sensitive functions.
## Example
iex> rel = Timex.Utils.get_otp_release
...> '\#{rel}' == :erlang.system_info(:otp_release)
true
"""
def get_otp_release do
case Process.get(:current_otp_release) do
nil ->
case ("#{:erlang.system_info(:otp_release)}" |> Integer.parse) do
{ver, _} when is_integer(ver) ->
Process.put(:current_otp_release, ver)
ver
_ ->
end
ver -> ver
end
end
@doc """
Loads all modules that extend a given module in the current code path.
The convention is that it will fetch modules with the same root namespace,
and that are suffixed with the name of the module they are extending.
## Example
iex> Timex.Utils.get_plugins(Timex.Parse.DateTime.Tokenizer) |> Enum.sort
[Timex.Parse.DateTime.Tokenizers.Default, Timex.Parse.DateTime.Tokenizers.Strftime]
"""
@spec get_plugins(atom) :: list(atom)
def get_plugins(plugin_type) when is_atom(plugin_type) do
case Process.get(:timex_plugins) do
plugins when is_list(plugins) ->
plugins
_ ->
plugins = available_modules(plugin_type) |> Enum.reduce([], &load_plugin/2)
Process.put(:timex_plugins, plugins)
plugins
end
end
@spec load_plugin(atom, list(atom)) :: list(atom) | no_return
defp load_plugin(module, modules) do
if Code.ensure_loaded?(module), do: [module | modules], else: modules
end
@spec available_modules(atom) :: Enumerable.t
defp available_modules(plugin_type) do
apps_path = Mix.Project.build_path |> Path.join("lib")
case apps_path |> File.ls do
{:ok, apps} ->
apps
|> Stream.map(&(Path.join([apps_path, &1, "ebin"])))
|> Stream.map(fn app_path ->
case app_path |> File.ls do
{:ok, files} -> files |> Enum.map(&(Path.join(app_path, &1)))
_ -> []
end
end)
|> Stream.flat_map(&(&1))
|> Stream.filter(&(String.ends_with?(&1, ".beam")))
|> Stream.map(fn path ->
{:ok, {module, chunks}} = :beam_lib.chunks('#{path}', [:attributes])
{module, get_in(chunks, [:attributes, :behaviour])}
end)
|> Stream.filter(fn {_module, behaviours} ->
is_list(behaviours) && plugin_type in behaviours
end)
|> Enum.map(fn {module, _} -> module end)
_ ->
[]
end
end
end