Skip to content

DOBRO/uef-lib

Repository files navigation

uef-lib

uef-lib on Hex.pm Build Status Code coverage License

uef-lib is a Useful Erlang Functions Library that provides modules for manipulating lists, binaries, maps, numbers, date and time. It can be used in OTP applications and contains some functions optimized for performance in specific cases (e.g. for file I/O operations or binary transformations).

Erlang/OTP 19 or higher is required.

See how to build and test.


Table of Contents

Installation

For Erlang projects

Add uef-lib as a dependency to your rebar.config file:

{deps, [
  {uef, "2.6.0"}
]}.

For Elixir projects

Add uef-lib as a dependency to your mix.exs file:

defp deps do
  [
    {:uef, "~> 2.6.0"}
  ]
end

Modules

Documentation

Module uef_bin


uef_bin:chomp/1

uef_bin:chomp(Binary1 :: binary()) -> Binary2 :: binary().

Removes all trailing \n and \r characters from Binary1.

Examples:

> uef_bin:chomp(<<"string\r\n">>).
<<"string">>

> uef_bin:chomp(<<"string\r\n\r\n">>).
<<"string">>

> uef_bin:chomp(<<"string\n\n\n\n">>).
<<"string">>

> uef_bin:chomp(<<"string\r\r\r\r">>).
<<"string">>

uef_bin:binary_join/2

uef_bin:binary_join(ListOfBinaries, Separator) -> Binary.

Joins a list of binaries with separator into a single binary. Returns binary.

Example:

> uef_bin:binary_join([<<"www">>, <<"example">>, <<"com">>], <<".">>).
<<"www.example.com">>

uef_bin:repeat/2

uef_bin:repeat(Binary1, N) -> Binary2.

Returns binary Binary2 consisting of Binary1 repeated N times.

Examples:

> uef_bin:repeat(<<"a">>, 10).
<<"aaaaaaaaaa">>

> uef_bin:repeat(<<"0">>, 3).
<<"000">>

> uef_bin:repeat(<<0>>, 3).
<<0,0,0>>

> uef_bin:repeat(<<1,1>>, 3).
<<1,1,1,1,1,1>>

> uef_bin:repeat(<<"abc">>, 3).
<<"abcabcabc">>

uef_bin:reverse/1

uef_bin:reverse(Binary1) -> Binary2.

Returns a binary in reverse byte order.

Note: this function is not intended to work with UTF-8 binary strings. To get a binary in reverse character order, use uef_bin:reverse_utf8/1 instead.

Examples:

> uef_bin:reverse(<<"ABCDEFGH">>).
<<"HGFEDCBA">>

> uef_bin:reverse(<<1,2,3,4,5>>).
<<5,4,3,2,1>>

> uef_bin:reverse(<<>>).
<<>>

uef_bin:reverse_utf8/1

uef_bin:reverse_utf8(UTF8_Binary1) -> UTF8_Binary2.

Returns a binary in reverse character order. Intended to work with UTF-8 binary strings.

Examples:

> uef_bin:reverse_utf8(<<"ABCDEFGH">>).
<<"HGFEDCBA">>

> uef_bin:reverse_utf8(<<1,2,3,4,5>>).
<<5,4,3,2,1>>

> uef_bin:reverse_utf8(<<"die Straße"/utf8>>).
<<"eßartS eid"/utf8>>

> uef_bin:reverse_utf8(<<"АБВГДЕЁЖ"/utf8>>) =:= <<"ЖЁЕДГВБА"/utf8>>.
true

> uef_bin:reverse_utf8(<<1, 2, 3, "АБВГДЕЁЖ"/utf8, 4, 5, 6, 7>>) =:= <<7, 6, 5, 4, "ЖЁЕДГВБА"/utf8, 3, 2, 1>>.
true

> uef_bin:reverse_utf8(<<"這條街"/utf8>>) =:= <<"街條這"/utf8>>.
true

> uef_bin:reverse_utf8(<<"こんにちは"/utf8>>) =:= <<"はちにんこ"/utf8>>.
true

uef_bin:split/2

uef_bin:split(Binary, Splitter) -> ListOfBinaries.

Splits binary Binary with splitter Splitter into a list of binaries. Works as binary:split/2 but is more performant in simple cases.

Examples:

> uef_bin:split(<<".www.example.com.">>, <<".">>).
[<<>>,<<"www">>,<<"example">>,<<"com">>,<<>>]

> uef_bin:split(<<"www.example.com">>, <<".">>).
[<<"www">>,<<"example">>,<<"com">>]

> uef_bin:split(<<"www.example.com">>, <<"A">>).
[<<"www.example.com">>]

uef_bin:split/3

uef_bin:split(Binary, Splitter, 'trim_all') -> ListOfBinaries.

Splits binary Binary with splitter Splitter into a list of binaries. Works as uef_bin:split/2 but removes all epmty (<<>>) chunks. It can be used in simple cases instead of binary:split/3 for the reason that it’s more performant.

Example:

> uef_bin:split(<<"..www.example.com.">>, <<".">>, trim_all).
[<<"www">>,<<"example">>,<<"com">>]

uef_bin:replace/3

uef_bin:replace(Binary1, Chars, OtherChars) -> Binary2.

Replaces chars Chars with other chars OtherChars in binary Binary1 and returns another binary Binary2. Works as binary:replace/3 but more permormant and can be used in simple cases.

Examples:

> uef_bin:replace(<<"abcdefgbc">>, <<"bc">>, <<"ZZ">>).
<<"aZZdefgZZ">>

> uef_bin:replace(<<"abcdefgbc">>, <<"d">>, <<"ZZ">>).
<<"abcZZefgbc">>

uef_bin:replace_chars/3

uef_bin:replace_chars(Binary1, ListOfCharsToReplace, OtherChars) -> Binary2.

Replaces chars inluded in list ListOfCharsToReplace with other chars OtherChars in binary Binary1 and returns another binary Binary2.

Examples:

uef_bin:replace_chars(<<"..www.example.com.">>, [<<".">>], <<>>).
<<"wwwexamplecom">>

uef_bin:replace_chars(<<"..www.example.com.">>, [<<".">>, <<"w">>], <<>>).
<<"examplecom">>

uef_bin:random_latin_binary/2

uef_bin:random_latin_binary(Length, CaseFlag) -> RandomLatinBinary.

Returns a random binary of size Length consisting of latins [a-zA-Z] and digits [0-9]. The second argument CaseFlag corresponds to a letter case, an atom 'lower', 'upper' or 'any'.

Examples:

> uef_bin:random_latin_binary(10, lower).
<<"n0ui89sfsb">>

> uef_bin:random_latin_binary(10, upper).
<<"S11Y3DHEJI">>

> uef_bin:random_latin_binary(10, any).
<<"mTa9Lj7KUN">>

uef_bin:random_binary_from_chars/2

uef_bin:random_binary_from_chars(Length, Chars) -> RandomCharsBinary.

Generates and returns a binary of size Length which consists of the given characters Chars.

Example:

> uef_bin:random_binary_from_chars(16, <<"ErlangForever">>).
<<"eFveerorreravgng">>

uef_bin:numeric_prefix/1

uef_bin:numeric_prefix(Binary) -> DigitsOnlyOrEmptyBinary.

Returns new binary DigitsOnlyBinary which consists of digits [0-9] wich are at the beginning in the given binary Binary. If Binary does not begin with digit, this function returns empty binary (<<>>).

Examples:

> uef_bin:numeric_prefix(<<"3456sld1knskjd">>).
<<"3456">>

> uef_bin:numeric_prefix(<<"ddd3456sld1knskjd">>).
<<>>

uef_bin:strip_left/2

uef_bin:strip_left(Binary1, Chars) -> Binary2.

Types:

Binary1 :: binary().
Chars :: binary() | integer().
Binary2 :: binary().

Removes leading Chars from Binary1 and returns Binary2.

Examples:

> uef_bin:strip_left(<<"www.example.com">>, <<"w">>).
<<".example.com">>

> uef_bin:strip_left(<<"www.example.com">>, <<"ww">>).
<<"w.example.com">>

> uef_bin:strip_left(<<11, 11, 11, 12, 13, 14>>, 11).
<<12,13,14>>

> uef_bin:strip_left(<<"ААААБВГДЕЁЖ"/utf8>>, <<"А"/utf8>>) =:= <<"БВГДЕЁЖ"/utf8>>.
true

> uef_bin:strip_left(<<"這這這這條街"/utf8>>, <<""/utf8>>) =:= <<"條街"/utf8>>.
true

uef_bin:strip_right/2

uef_bin:strip_right(Binary1, Chars) -> Binary2.

Types:

Binary1 :: binary().
Chars :: binary() | integer().
Binary2 :: binary().

Removes trailing Chars from Binary1 and returns Binary2.

Examples:

> uef_bin:strip_right(<<"example.comwww">>, <<"w">>).
<<"example.com">>

> uef_bin:strip_right(<<"example.comwww">>, <<"ww">>).
<<"example.comw">>

> uef_bin:strip_right(<<1, 2, 3, 4, 5, 5, 5>>, 5).
<<1,2,3,4>>

> uef_bin:strip_right(<<"АБВГДЕЁЖЖЖЖ"/utf8>>, <<"Ж"/utf8>>) =:= <<"АБВГДЕЁ"/utf8>>.
true

> uef_bin:strip_right(<<"這條街街街街"/utf8>>, <<""/utf8>>) =:= <<"這條"/utf8>>.
true

uef_bin:strip_both/2

uef_bin:strip_both(Binary1, Chars) -> Binary2.

Types:

Binary1 :: binary().
Chars :: binary() | integer().
Binary2 :: binary().

Removes leading and trailing Chars from Binary1 and returns Binary2.

Examples:

> uef_bin:strip_both(<<"www.example.www">>, <<"w">>).
<<".example.">>

> uef_bin:strip_both(<<"com.example.com">>, <<"com">>).
<<".example.">>

> uef_bin:strip_both(<<5,5,5, 1,2,3,4, 5,5,5>>, 5).
<<1,2,3,4>>

> uef_bin:strip_both(<<"ЖЖЖЖАБВГДЕЁЖЖЖЖ"/utf8>>, <<"Ж"/utf8>>) =:= <<"АБВГДЕЁ"/utf8>>.
true

> uef_bin:strip_both(<<"街街街街這條街街街街"/utf8>>, <<""/utf8>>) =:= <<"這條"/utf8>>.
true

Module uef_crypt


uef_crypt:md5_hex/1

uef_crypt:md5_hex(IoData) -> Binary.

Returns binary Binary in hexadecimal form of md5 hash of the argument IoData.

Examples:

> uef_crypt:md5_hex("abcd").
<<"e2fc714c4727ee9395f324cd2e7f331f">>

> uef_crypt:md5_hex(<<"привет"/utf8>>).
<<"608333adc72f545078ede3aad71bfe74">>

> uef_crypt:md5_hex(["how", ["is", ["it"]], "going", $?]).
<<"eb89df06495cef83e3ec185aefe81d0e">>

Module uef_encode


uef_encode:html_encode_bin/1

uef_encode:html_encode_bin(Html) -> EncodedBinary.

Takes argument Html, replaces some unsafe symbols with their appropriate HTML entities and returns binary.

Examples:

> uef_encode:html_encode_bin("<>&©\n").
<<"&lt;&gt;&amp;&copy;<br/>&trade;">>

> uef_encode:html_encode_bin("♦±Σ").
<<"&#9830;&plusmn;&Sigma;">>

uef_encode:html_encode_list/1

uef_encode:html_encode_list(Html) -> EncodedList.

Takes argument Html, replaces some unsafe symbols with their appropriate HTML entities and returns list of binaries.

Examples:

> uef_encode:html_encode_list("<>&©\n").
[<<"&lt;">>,<<"&gt;">>,<<"&amp;">>,<<"&copy;">>,<<"<br/>">>,<<"&trade;">>]

> uef_encode:html_encode_list("♦±Σ").
[<<"&#9830;">>,<<"&plusmn;">>,<<"&Sigma;">>]

uef_encode:win_to_utf8/1

uef_encode:win_to_utf8(Binary1251) -> BinaryUtf8.

Converts cp1251 binary to utf-8 binary.

Example:

file_1251_to_utf8() ->
    File1251 = "1251.txt",
    FileUtf8 = "utf8.txt",
    {ok, Bin1251} = file:read_file(File1251),
    BinUtf8 = uef_encode:win_to_utf8(Bin1251), %converting
    file:write_file(FileUtf8, BinUtf8).

Module uef_file


uef_file:read_file_info_fast/1

uef_file:read_file_info_fast(Filename) -> {ok, FileInfo} | {error, Reason}.

Retrieves information about local file. Returns {ok, FileInfo} if successful, otherwise {error, Reason}. Works as file:read_file_info/2 but optimized for local files. This is a wrapper of:

file:read_file_info(Filename, [raw, {time, posix}]).


uef_file:read_file_fast/1

uef_file:read_file_fast(Filename) -> {ok, BinaryData} | {error, Reason}.

Reads contents of local file Filename and returns {ok, BinaryData}, where BinaryData is a binary data object that contains the contents of Filename, or {error, Reason} if an error occurs. This function is optimized for reading contents of local files, as no Erlang process is used. It calls file:open/2 with options [read, raw, binary].


Module uef_format


uef_format:format_bytes/1

uef_format:format_bytes(Bytes) -> FormattedBytes.

The same as uef_format:format_bytes(Bytes, #{}). See uef_format:format_bytes/2 docs.

Examples:

> uef_format:format_bytes(1024).
<<"1KB">>

> uef_format:format_bytes(1000).
<<"0KB">>

> uef_format:format_bytes(1048576).
<<"1MB">>

> uef_format:format_bytes(10485760).
<<"10MB">>

uef_format:format_bytes/2

uef_format:format_bytes(Bytes, Options) -> FormattedBytes.

Types:

Bytes :: integer().

Options :: #{
    units => Units,
    base => Base,
    to_type => ToType,
    sep => Separator
}.

Units :: auto | MultiUnits.
MultiUnits :: 'KB' | 'MB' | 'GB' | 'TB' | 'PB' | 'EB' | 'ZB' | 'YB'.
Base :: 2 | 10.
ToType :: bin | int.
Separator :: binary().

FormattedBytes :: binary() | integer() | {integer(), MultiUnits}.

Default Options:

#{ units => auto, base => 2, to_type => bin, sep => <<>> }.

Converts bytes Bytes to multiples of bytes. The datatype of the return value depends on ToType and Units:

  • if ToType is bin, it returns binary();

  • if ToType is int, it returns integer();

  • if ToType is int and Units is auto, tuple {integer(), MultiUnits} is returned.

The value of Base affects the conversion of Bytes to multiples:

  • Base = 2 means that 1KB = 1024 bytes, 1MB = 1048576 bytes, …​;

  • Base = 10 means that 1KB = 1000 bytes, 1MB = 1000000 bytes, …​

If the value of Units is auto, bytes are converted to the most reasonable multiples of bytes.

Separator is a separator between integer value and Units. This option affects the result when ToType is bin.

Examples:

> uef_format:format_bytes(1000000, #{units => auto, base => 2}).
<<"976KB">>

> uef_format:format_bytes(1048576, #{units => auto, base => 2}).
<<"1MB">>

> uef_format:format_bytes(1048576, #{units => 'KB', base => 2}).
<<"1024KB">>

> uef_format:format_bytes(1048576, #{units => 'KB', base => 10}).
<<"1048KB">>

> uef_format:format_bytes(1048576, #{units => auto, base => 2, to_type => int}).
{1,'MB'}

> uef_format:format_bytes(1048576, #{units => 'KB', base => 2, to_type => int}).
1024

> uef_format:format_bytes(1048576, #{units => 'KB', to_type => bin, sep => <<" ">>}).
<<"1024 KB">>

> uef_format:format_bytes(1048576, #{units => 'KB', to_type => bin, sep => <<"|">>}).
<<"1024|KB">>

uef_format:format_number/3

uef_format:format_number(Number, Precision, Decimals) -> FormattedNumber.

The same as uef_format:format_number/4 with #{} as the forth argument. See uef_format:format_number/4 docs.

Examples:

> uef_format:format_number(199.4567, 2, 3).
<<"199.460">>

>uef_format:format_number(199.4567, 1, 3).
<<"199.500">>

> uef_format:format_number(199.4567, 0, 4).
<<"199.0000">>

> uef_format:format_number(199.4567, -1, 2).
<<"200.00">>

uef_format:format_number/4

uef_format:format_number(Number, Precision, Decimals, Options) -> FormattedNumber.

Formats Number by adding thousands separator between each set of 3 digits to the left of the decimal point, substituting Decimals for the decimal point, and rounding to the specified Precision. Returns a binary value.

Types:

Number :: number().
Precision :: integer().
Decimals :: non_neg_integer().
FormattedNumber :: binary().

Options is a map:

#{
    thousands_sep => binary() | string(), % Thousands separator
    decimal_point => binary() | string(), % Decimal point
    cur_symbol => binary() | string(), %% Currency symbol
    cur_pos => 'left' | 'right', % Currency position against price (left or right)
    cur_sep => binary() | string() % Separator between currency and price
}

Note: to get maximum performance use binary values for options thousands_sep, decimal_point, cur_symbol and cur_sep instead of strings.

Examples:

> uef_format:format_number(1234567890.4567, 2, 2, #{}).
<<"1234567890.46">>

> uef_format:format_number(1234567890.4567, 2, 2, #{thousands_sep => ",", cur_symbol => "$"}).
<<"$1,234,567,890.46">>

> uef_format:format_number(1234567890.4567, 2, 2, #{
    thousands_sep => ",",
    cur_symbol => "USD",
    cur_sep => " ", % whitespace
    cur_pos => right}).
<<"1,234,567,890.46 USD">>

> uef_format:format_number(1234567890.4567, 2, 4, #{
    thousands_sep => ",",
    decimal_point => "==",
    cur_symbol => "USD",
    cur_sep => " ",
    cur_pos => left}).
<<"USD 1,234,567,890==4600">>

> uef_format:format_number(1234567890.4567, 2, 4, #{
    thousands_sep => <<",">>, % binary()
    decimal_point => <<".">>, % binary()
    cur_symbol => <<"USD">>, % binary()
    cur_sep => <<" ">>, % binary()
    cur_pos => left}).
<<"USD 1,234,567,890.4600">>

uef_format:format_price/1

uef_format:format_price(Number) -> FormattedPrice.

Formats Number in price-like style. Returns a binary containing FormattedPrice formatted with a precision of 2 and decimal digits of 2.

The same as uef_format:format_price/2 with a precision of 2 as the second argument. See uef_format:format_price/2 docs.

Examples:

> uef_format:format_price(199).
<<"199.00">>

> uef_format:format_price(199.9876).
<<"199.99">>

uef_format:format_price/2

uef_format:format_price(Number, Precision) -> FormattedPrice.

Formats Number in price-like style. Returns a binary containing FormattedPrice formatted with a specified precision as the second argument and decimal digits of 2.

The same as uef_format:format_price/3 with #{} as the third argument. See uef_format:format_price/3 docs.

Example:

> uef_format:format_price(1999.9876, 4).
<<"1999.99">>

uef_format:format_price/3

uef_format:format_price(Number, Precision, CurrencySymbol_OR_Options) -> FormattedPrice.

Formats Number in price-like style. Returns a binary containing FormattedPrice formatted with a specified precision as the second argument, decimal digits of 2, and with currency symbol (or options) as the third argument.

If CurrencySymbol_OR_Options is a map the functions works as uef_format:format_number/4 with decimal digits of 2 as the third argument and with options as the forth one.

If CurrencySymbol_OR_Options is a binary or a string, the corresponding currency symbol is added to the left.

Examples:

> uef_format:format_price(1000.8767, 4, #{}).
<<"1000.88">>


> uef_format:format_price(1000.8767, 4, #{
    thousands_sep => ",",
    cur_symbol => "USD",
    cur_sep => " ",
    cur_pos => right}).
<<"1,000.88 USD">>


> uef_format:format_price(1000.8767, 4, #{
    thousands_sep => ",",
    cur_symbol => <<"руб."/utf8>>,
    cur_sep => " ",
    cur_pos => right}).
<<49,44,48,48,48,46,56,56,32,209,128,209,131,208,177,46>> % <<"1,000.88 руб."/utf8>>.


> uef_format:format_price(1000.8767, 4, "$").
<<"$1000.88">>


> uef_format:format_price(99.999, 2, "$").
<<"$100.00">>


> uef_format:format_price(99.99, 2, "$").
<<"$99.99">>


> uef_format:format_price(99.99, 2, <<""/utf8>>).
<<226,130,172,57,57,46,57,57>> % <<"€99.99"/utf8>>

Module uef_lists


uef_lists:split_list_into_chunks/2

uef_lists:split_list_into_chunks(List, MaxLen) -> [List1, List2, ..., ListN].

Splits List into list of lists [List1, List2, …​, ListN] where List1, List2, …​, ListN are lists with maximum MaxLen elements.

Examples:

> uef_lists:split_list_into_chunks([1,2,3,4,5,6,7,8], 1).
[[1],[2],[3],[4],[5],[6],[7],[8]]

> uef_lists:split_list_into_chunks([1,2,3,4,5,6,7,8], 2).
[[1,2],[3,4],[5,6],[7,8]]

> uef_lists:split_list_into_chunks([1,2,3,4,5,6,7,8], 3).
[[1,2,3],[4,5,6],[7,8]]

> uef_lists:split_list_into_chunks([1,2,3,4,5,6,7,8], 4).
[[1,2,3,4],[5,6,7,8]]

> uef_lists:split_list_into_chunks([1,2,3,4,5,6,7,8], 8).
[[1,2,3,4,5,6,7,8]]

> uef_lists:split_list_into_chunks([1,2,3,4,5,6,7,8], 9).
[[1,2,3,4,5,6,7,8]]

> uef_lists:split_list_into_chunks([1,2,3,4,5,6,7,8], 99).
[[1,2,3,4,5,6,7,8]]

uef_lists:lists_to_list_of_tuples/2

uef_lists:lists_to_list_of_tuples(List1, List2) -> List3.

Transforms two lists into one list of two-tuples, where the first element of each tuple is taken from the first list and the second element is taken from the second list one by one.

Examples:

> uef_lists:lists_to_list_of_tuples([a,b,c], [1,2]).
[{a,1},{a,2},{b,1},{b,2},{c,1},{c,2}]

> uef_lists:lists_to_list_of_tuples([a,b,c], [1,2,3]).
[{a,1},{a,2},{a,3},{b,1},{b,2},{b,3},{c,1},{c,2},{c,3}]

uef_lists:lists_to_list_of_tuples/3

uef_lists:lists_to_list_of_tuples(List1, List2, List3) -> List4.

Transforms three lists into one list of three-tuples, where the first element of each tuple is taken from the first list, the second element is taken from the second list one by one, and the third element is taken from the third list one by one.

Examples:

> uef_lists:lists_to_list_of_tuples([a1,b1], [a2,b2], [a3,b3]).
[{a1,a2,a3},
 {a1,a2,b3},
 {a1,b2,a3},
 {a1,b2,b3},
 {b1,a2,a3},
 {b1,a2,b3},
 {b1,b2,a3},
 {b1,b2,b3}]

> uef_lists:lists_to_list_of_tuples([a1,b1], [a2,b2,c2], [a3,b3]).
[{a1,a2,a3},
 {a1,a2,b3},
 {a1,b2,a3},
 {a1,b2,b3},
 {a1,c2,a3},
 {a1,c2,b3},
 {b1,a2,a3},
 {b1,a2,b3},
 {b1,b2,a3},
 {b1,b2,b3},
 {b1,c2,a3},
 {b1,c2,b3}]

uef_lists:search/2

uef_lists:search(Pred, List) -> {value, Value} | false.

If there is a Value in List such that Pred(Value) returns true, returns {value, Value} for the first such Value, otherwise returns false.

Note: Since OTP 21.0 use BIF lists:search/2 instead.


Module uef_maps


uef_maps:delete_nested/2

uef_maps:delete_nested(Keys, Map1) -> {ok, Map2} | {error, {badkey, SomeKey}} | {error, empty_keys}.

Say, Keys is a list of elements Key1, Key2, …​, KeyN and Map1 has internal structure #{Key1 ⇒ #{Key2 ⇒ #{…​ ⇒ #{KeyN ⇒ ValueN}}}}. The function removes key KeyN, if it exists, and its associated value from the corresponding internal map and updates the entire structure of map Map1 getting new map Map2. There are three possible return values:

  • tuple {ok, Map2} if KeyN was removed;

  • tuple {error, {badkey, SomeKey}} if SomeKey does not exist in the structure of map Map1, where SomeKey is one of the elements of list Keys;

  • tuple {error, empty_keys} if Keys is empty list.

The call fails with a {badmap,Map1} exception if Map1 is not a map, or with a {badlist,Keys} exception if Keys is not a list.

Examples:

> Map1 = #{1 => #{2 => #{3 => val3, 33 => val33}}}.
#{1 => #{2 => #{3 => val3,33 => val33}}}

> uef_maps:delete_nested([], Map1).
{error,empty_keys}

> uef_maps:delete_nested([1], Map1).
{ok,#{}}

> uef_maps:delete_nested([1,2], Map1).
{ok,#{1 => #{}}}

> uef_maps:delete_nested([1,2,3], Map1).
{ok,#{1 => #{2 => #{33 => val33}}}}

> uef_maps:delete_nested([-1], Map1).
{error,{badkey,-1}}

> uef_maps:delete_nested([1,-2], Map1).
{error,{badkey,-2}}

> uef_maps:delete_nested([1,2,-3], Map1).
{error,{badkey,-3}}

> uef_maps:delete_nested([1,2,3,4], Map1).
{error,{badkey,4}}

> uef_maps:delete_nested([1,2,3,4,5], Map1).
{error,{badkey,4}} % 4, not 5!

uef_maps:find_nested/2

uef_maps:find_nested(Keys, Map) -> {ok, Value} | error.

Traverses nested map Map (map of maps) deep through the keys that are elements of list Keys. Returns tuple {ok, Value}, where Value is the value associated with the last element of list Keys, or error if no value is found.

The call fails with a {badmap,Map} exception if Map is not a map, or with a {badlist,Keys} exception if Keys is not a list.

Examples:

> Value = abc, M3 = #{key4 => Value}, M2 = #{key3 => M3}, M1 = #{key2 => M2}, M0 = #{key1 => M1}.
#{key1 => #{key2 => #{key3 => #{key4 => abc}}}} % M0

> uef_maps:find_nested([key1], M0).
{ok,#{key2 => #{key3 => #{key4 => abc}}}} % {ok, M1}

> uef_maps:find_nested([key1,key2], M0).
{ok,#{key3 => #{key4 => abc}}} % {ok, M2}

> uef_maps:find_nested([key1,key2,key3], M0).
{ok,#{key4 => abc}} % {ok, M3}

> uef_maps:find_nested([key1,key2,key3,key4], M0).
{ok,abc} % {ok, Value}

> uef_maps:find_nested([-1], M0).
error

> uef_maps:find_nested([key1,key2,-3,key4], M0).
error

> uef_maps:find_nested([key1,key2,key3,-4], M0).
error

> uef_maps:find_nested([key1,key2,key3,key4,key5], M0).
** exception error: {badmap,abc}

uef_maps:get_nested/2

uef_maps:get_nested(Keys, Map) -> Value.

Traverses nested map Map (map of maps) deep through the keys that are elements of list Keys. Returns value Value associated with the last element of list Keys.

The call fails with a {badmap,Map} exception if Map is not a map, or with a {badkeys,Keys} exception if no value is found, or with a {badlist,Keys} exception if Keys is not a list.

Examples:

> Value = abc, M3 = #{key4 => Value}, M2 = #{key3 => M3}, M1 = #{key2 => M2}, M0 = #{key1 => M1}.
#{key1 => #{key2 => #{key3 => #{key4 => abc}}}} % M0

> uef_maps:get_nested([key1], M0).
#{key2 => #{key3 => #{key4 => abc}}} % M1

> uef_maps:get_nested([key1,key2], M0).
#{key3 => #{key4 => abc}} % M2

> uef_maps:get_nested([key1,key2,key3], M0).
#{key4 => abc} % M3

> uef_maps:get_nested([key1,key2,key3,key4], M0).
abc % Value

uef_maps:get_nested/3

uef_maps:get_nested(Keys, Map, Default) -> Value | Default.

Traverses nested map Map (map of maps) deep through the keys that are elements of list Keys. Returns value Value associated with the last element of list Keys. If no value is found, Default is returned.

The call fails with a {badmap,Map} exception if Map is not a map, or with a {badlist,Keys} exception if Keys is not a list. It does not fail if any internal value associated with any element of list Keys is not a map.

Examples:

> Value = abc, Default = default, M3 = #{key4 => Value}, M2 = #{key3 => M3}, M1 = #{key2 => M2}, M0 = #{key1 => M1}.
#{key1 => #{key2 => #{key3 => #{key4 => abc}}}} % M0.

> uef_maps:get_nested([key1,key2,key3,key4], M0, Default).
abc % Value

> uef_maps:get_nested([key1,key2,key3,-4], M0, Default).
default % Default

> uef_maps:get_nested([key1,key2,-3,key4], M0, Default).
default % Default

> uef_maps:get_nested([key1,key2,key3,key4,key5], M0, Default).
default % Default anyway. Doesn't fail

uef_maps:is_key_nested/2

uef_maps:is_key_nested(Keys, Map) -> true | false.

Returns true if map Map contains submaps as values associated with their own key corresponding to the element of list Keys, and returns false otherwise.

The call fails with a {badmap,Map} exception if Map is not a map, or with a {badlist,Keys} exception if Keys is not a list.

Examples:

> M3 = #{key4 => value}, M2 = #{key3 => M3}, M1 = #{key2 => M2}, M0 = #{key1 => M1}.
#{key1 => #{key2 => #{key3 => #{key4 => value}}}} % M0

> uef_maps:is_key_nested([key1,key2,key3,key4], M0).
true

> uef_maps:is_key_nested([key1,key2,key3], M0).
true

> uef_maps:is_key_nested([key1,key2], M0).
true

> uef_maps:is_key_nested([key1], M0).
true

> uef_maps:is_key_nested([], M0).
false

> uef_maps:is_key_nested([key1,key2,key3,key4,key5], M0).
false

> uef_maps:is_key_nested([-1,key2,key3,key4], M0).
false

> uef_maps:is_key_nested([key1,-2,key3,key4], M0).
false

uef_maps:new_nested/1

uef_maps:new_nested(Keys) -> Map.

Same as uef_maps:new_nested(Keys, #{}). See docs of uef_maps:new_nested/2.


uef_maps:new_nested/2

uef_maps:new_nested(Keys, Value) -> Map.

Returns new nested map Map with the deepest map #{LastKey ⇒ Value}, where LastKey is the last element of list Keys.

The call fails with a {badlist,Keys} exception if Keys is not a list.

Examples:

> uef_maps:new_nested([], value).
#{}

> uef_maps:new_nested([key], value).
#{key => value}

> uef_maps:new_nested([key1, key2], value).
#{key1 => #{key2 => value}}

> uef_maps:new_nested([key1, key2, key3], value).
#{key1 => #{key2 => #{key3 => value}}}

uef_maps:put_nested/3

uef_maps:put_nested(Keys, Value, Map1) -> Map2.

Say, Keys is a list of elements Key1, Key2, …​, KeyN and Map1 has internal structure #{Key1 ⇒ #{Key2 ⇒ #{…​ ⇒ #{KeyN ⇒ ValueN}}}}. The function associates KeyN with value Value and updates the entire structure of map Map1 returning new map Map2. If some keys from list Keys are not in the structure of map Map1, they will be inserted into the structure of map Map2 in the same order.

The call fails with a {badmap,Map1} exception if Map1 is not a map, or with a {badlist,Keys} exception if Keys is not a list.

Examples:

> Map1 = #{1 => #{2 => #{3 => val3}}}.
#{1 => #{2 => #{3 => val3}}} % Map1

> uef_maps:put_nested([], new_value, Map1).
#{1 => #{2 => #{3 => val3}}} % Map1 (empty list of keys)

> uef_maps:put_nested([1], new_value, Map1).
#{1 => new_value}

> uef_maps:put_nested([1,2], new_value, Map1).
#{1 => #{2 => new_value}}

> uef_maps:put_nested([1,2,3], new_value, Map1).
#{1 => #{2 => #{3 => new_value}}}

> uef_maps:put_nested([1,2,-3], new_value, Map1).
#{1 => #{2 => #{-3 => new_value,3 => val3}}}

> uef_maps:put_nested([1,2,3,4], new_value, Map1).
#{1 => #{2 => #{3 => #{4 => new_value}}}}

> uef_maps:put_nested([-1], new_value, Map1).
#{-1 => new_value,1 => #{2 => #{3 => val3}}}

> uef_maps:put_nested([1,-2], new_value, Map1).
#{1 => #{-2 => new_value,2 => #{3 => val3}}}

> uef_maps:put_nested([1,2,-3], new_value, Map1).
#{1 => #{2 => #{-3 => new_value,3 => val3}}}

> uef_maps:put_nested([1,2,3,-4], new_value, Map1).
#{1 => #{2 => #{3 => #{-4 => new_value}}}}

uef_maps:remove_nested/2

uef_maps:remove_nested(Keys, Map1) -> Map2.

Say, Keys is a list of elements Key1, Key2, …​, KeyN and Map1 has internal structure #{Key1 ⇒ #{Key2 ⇒ #{…​ ⇒ #{KeyN ⇒ ValueN}}}}. The function removes key KeyN, if it exists, and its associated value from the corresponding internal map and updates the entire structure of map Map1 returning new map Map2. If some keys from list Keys are not in the structure of map Map1 the function returns a map without changes.

The call fails with a {badmap,Map1} exception if Map1 is not a map, or with a {badlist,Keys} exception if Keys is not a list.

Examples:

> Map1 = #{1 => #{2 => #{3 => val3, 33 => val33}}}.
#{1 => #{2 => #{3 => val3,33 => val33}}}

> uef_maps:remove_nested([], Map1).
#{1 => #{2 => #{3 => val3,33 => val33}}}  % Map1 (empty list of keys)

> uef_maps:remove_nested([1], Map1).
#{}

> uef_maps:remove_nested([1,2], Map1).
#{1 => #{}}

> uef_maps:remove_nested([1,2,3], Map1).
#{1 => #{2 => #{33 => val33}}}

> uef_maps:remove_nested([-1], Map1).
#{1 => #{2 => #{3 => val3,33 => val33}}}  % Map1

> uef_maps:remove_nested([1,-2], Map1).
#{1 => #{2 => #{3 => val3,33 => val33}}}  % Map1

> uef_maps:remove_nested([1,2,-3], Map1).
#{1 => #{2 => #{3 => val3,33 => val33}}}  % Map1

> uef_maps:remove_nested([1,2,3,4], Map1).
#{1 => #{2 => #{3 => val3,33 => val33}}}  % Map1

> uef_maps:remove_nested([1,2,3,4,5], Map1).
#{1 => #{2 => #{3 => val3,33 => val33}}}  % Map1

uef_maps:take_nested/2

uef_maps:take_nested(Keys, Map1) -> {Value, Map2} | error.

Say, Keys is a list of elements Key1, Key2, …​, KeyN and Map1 has internal structure #{Key1 ⇒ #{Key2 ⇒ #{…​ ⇒ #{KeyN ⇒ Value}}}}. The function removes key KeyN, if it exists, and its associated value Value from the corresponding internal map and updates the entire structure of map Map1 returning tuple {Value, Map2}. If some keys from list Keys are not in the structure of map Map1 the function returns error.

The call fails with a {badmap,Map1} exception if Map1 is not a map, or with a {badlist,Keys} exception if Keys is not a list.

Examples:

> Map1 = #{1 => #{2 => #{3 => val3, 33 => val33}}}.
#{1 => #{2 => #{3 => val3,33 => val33}}}

> uef_maps:take_nested([], Map1).
error

> uef_maps:take_nested([1], Map1).
{#{2 => #{3 => val3,33 => val33}},#{}}

> uef_maps:take_nested([1,2], Map1).
{#{3 => val3,33 => val33},#{1 => #{}}}

> uef_maps:take_nested([1,2,3], Map1).
{val3,#{1 => #{2 => #{33 => val33}}}}

> uef_maps:take_nested([-1], Map1).
error

> uef_maps:take_nested([1,-2], Map1).
error

> uef_maps:take_nested([1,2,-3], Map1).
error

> uef_maps:take_nested([1,2,3,4], Map1).
error

> uef_maps:take_nested([1,2,3,4,5], Map1).
error

uef_maps:update_nested/3

uef_maps:update_nested(Keys, Value, Map1) -> Map2.

Works similar to uef_maps:put_nested/3 with the difference that it fails with a {badkey,SomeKey} exception if SomeKey does not exist in the structure of map Map1, where SomeKey is one of the elements of list Keys.

The call also fails with a {badmap,Map1} exception if Map1 is not a map, or with a {badlist,Keys} exception if Keys is not a list.

Examples:

> Map1 = #{1 => #{2 => #{3 => val3}}}.
#{1 => #{2 => #{3 => val3}}} % Map1

> uef_maps:update_nested([], new_value, Map1).
#{1 => #{2 => #{3 => val3}}} % Map1 (empty list of keys)

> uef_maps:update_nested([1], new_value, Map1).
#{1 => new_value}

> uef_maps:update_nested([1,2], new_value, Map1).
#{1 => #{2 => new_value}}

> uef_maps:update_nested([1,2,3], new_value, Map1).
#{1 => #{2 => #{3 => new_value}}}

> uef_maps:update_nested([1,2,3,4], new_value, Map1).
** exception error: {badkey,4}

> uef_maps:update_nested([1,2,3,4,5], new_value, Map1).
** exception error: {badkey,4} % 4, not 5! because 4 is before

> uef_maps:update_nested([-1], new_value, Map1).
** exception error: {badkey,-1}

> uef_maps:update_nested([1,-2], new_value, Map1).
** exception error: {badkey,-2}

> uef_maps:update_nested([1,2,-3], new_value, Map1).
** exception error: {badkey,-3}

> uef_maps:update_nested([1,2,3,-4], new_value, Map1).
** exception error: {badkey,-4}

Module uef_num


uef_num:ctz/1

uef_num:ctz(Integer) -> TrailingZeros.

Counts trailing zeros in the binary representation of a positive integer. Returns the number of zero bits following the least significant one bit.

The call fails with a {badarg,Integer} exception if Integer is not a positive integer.

Examples:

> uef_num:ctz(2#10001000).
3

> uef_num:ctz(7).
0

> uef_num:ctz(2#00101010).
1

> uef_num:ctz(2#1000000000000000000000000000000000000000000000000000000000000000).
63

> uef_num:ctz(2#1111111111111111111111111111111111111111111111111111111111111111).
0

> uef_num:ctz(16#FFFFFFFFFFFFFFFF).
0

uef_num:lsb_pos/1

uef_num:lsb_pos(Integer) -> Position.

Returns the position of the least significant bit (LSB) in the binary representation of a positive integer.

The call fails with a {badarg,Integer} exception if Integer is not a positive integer.

Examples:

> uef_num:lsb_pos(2#10001000).
4

> uef_num:lsb_pos(7).
1

> uef_num:lsb_pos(2#00101010).
2

> uef_num:lsb_pos(2#1000000000000000000000000000000000000000000000000000000000000000).
64

> uef_num:lsb_pos(2#1111111111111111111111111111111111111111111111111111111111111111).
1

> uef_num:lsb_pos(16#FFFFFFFFFFFFFFFF).
1

uef_num:msb_pos/1

uef_num:msb_pos(Integer) -> Position.

Returns the position of the most significant bit (MSB) in the binary representation of a positive integer.

The call fails with a {badarg,Integer} exception if Integer is not a positive integer.

Examples:

> uef_num:msb_pos(2#111).
3

> uef_num:msb_pos(7).
3

> uef_num:msb_pos(2#0010101).
5

> uef_num:msb_pos(2#1000000000000000000000000000000000000000000000000000000000000000).
64

> uef_num:msb_pos(2#1111111111111111111111111111111111111111111111111111111111111111).
64

> uef_num:msb_pos(16#FFFFFFFFFFFFFFFF).
64

uef_num:popcount/1

uef_num:popcount(Integer) -> OneBits.

Returns the number of 1’s (ones or one-bits) in the binary representation of a non-negative integer. Also known as population count, pop count, popcount, sideways sum, bit summation, or Hamming weight.

The call fails with a {badarg,Integer} exception if Integer is not a non-negative integer.

Examples:

> uef_num:popcount(7).
3

> uef_num:popcount(0).
0

> uef_num:popcount(2#1010101).
4

> uef_num:popcount(2#1000000000000000000000000000000000000000000000000000000000000000).
1

> uef_num:popcount(2#1111111111111111111111111111111111111111111111111111111111111111).
64

> uef_num:popcount(16#FFFFFFFFFFFFFFFF).
64

uef_num:round_number/2

uef_num:round_number(Number, Precision) -> Float.

Rounds the number to the specified precision.

Examples:

> uef_num:round_number(10, 2).
10.0

> uef_num:round_number(123.786, 2).
123.79

uef_num:round_price/1

uef_num:round_price(Number) -> Float.

Rounds the number to the precision of 2. The same as uef_num:round_number(Number, 2).


Module uef_time


uef_time:add_seconds/1

uef_time:add_seconds(Seconds) -> NewDateTime.

Same as uef_time:add_seconds(erlang:localtime(), Seconds). See docs of uef_time:add_seconds/2.

Types:

Seconds :: integer().
NewDateTime :: calendar:datetime().

uef_time:add_seconds/2

uef_time:add_seconds(DateOrDatetime, Seconds) -> NewDateTime.

Adds the number of seconds Seconds to DateOrDatetime and returns a new datetime value.

Types:

DateOrDatetime :: calendar:date() | calendar:datetime().
Seconds :: integer().
NewDateTime :: calendar:datetime().

Examples:

> uef_time:add_seconds({2019, 1, 1}, 10).
{{2019,1,1},{0,0,10}}

> uef_time:add_seconds({2019, 1, 1}, -10).
{{2018,12,31},{23,59,50}}

> uef_time:add_seconds({{2019, 1, 1}, {23, 59, 0}}, 10).
{{2019,1,1},{23,59,10}}

> uef_time:add_seconds({{2019, 1, 1}, {23, 59, 0}}, -10).
{{2019,1,1},{23,58,50}}

uef_time:add_minutes/1

uef_time:add_minutes(Minutes) -> NewDateTime.

Same as uef_time:add_seconds(Minutes * 60). See docs of uef_time:add_seconds/1.

Types:

Minutes :: integer().
NewDateTime :: calendar:datetime().

uef_time:add_minutes/2

uef_time:add_minutes(DateOrDatetime, Minutes) -> NewDateTime.

Adds the number of minutes Minutes to DateOrDatetime and returns a new datetime value.

Types:

DateOrDatetime :: calendar:date() | calendar:datetime().
Minutes :: integer().
NewDateTime :: calendar:datetime().

Examples:

> uef_time:add_minutes({2019, 1, 1}, 10).
{{2019,1,1},{0,10,0}}

> uef_time:add_minutes({2019, 1, 1}, -10).
{{2018,12,31},{23,50,0}}

> uef_time:add_minutes({{2019, 1, 1}, {23, 59, 0}}, 10).
{{2019,1,2},{0,9,0}}

> uef_time:add_minutes({{2019, 1, 1}, {0, 1, 0}}, -10).
{{2018,12,31},{23,51,0}}

uef_time:add_hours/1

uef_time:add_hours(Hours) -> NewDateTime.

Same as uef_time:add_seconds(Hours * 3600). See docs of uef_time:add_seconds/1.

Types:

Hours :: integer().
NewDateTime :: calendar:datetime().

uef_time:add_hours/2

uef_time:add_hours(DateOrDatetime, Hours) -> NewDateTime.

Adds the number of hours Hours to DateOrDatetime and returns a new datetime value.

Types:

DateOrDatetime :: calendar:date() | calendar:datetime().
Hours :: integer().
NewDateTime :: calendar:datetime().

Examples:

> uef_time:add_hours({2019, 1, 1}, 10).
{{2019,1,1},{10,0,0}}

> uef_time:add_hours({2019, 1, 1}, -10).
{{2018,12,31},{14,0,0}}

> uef_time:add_hours({{2019, 1, 1}, {23, 59, 0}}, 10).
{{2019,1,2},{9,59,0}}

> uef_time:add_hours({{2019, 1, 1}, {0, 1, 0}}, -10).
{{2018,12,31},{14,1,0}}

uef_time:add_days/1

uef_time:add_days(Days) -> NewDateTime.

Same as uef_time:add_seconds(Days * 86400). See docs of uef_time:add_seconds/1.

Types:

Days :: integer().
NewDateTime :: calendar:datetime().

uef_time:add_days/2

uef_time:add_days(DateOrDatetime, Days) -> NewDateOrDateTime.

Adds the number of days Days to DateOrDatetime and returns a new date or datetime value. The type of NewDateOrDateTime is the same as the type of DateOrDatetime.

Types:

DateOrDatetime :: calendar:date() | calendar:datetime().
Days :: integer().
NewDateOrDateTime :: calendar:date() | calendar:datetime().

Examples:

> uef_time:add_days({2019, 1, 1}, 10).
{2019,1,11}

> uef_time:add_days({2019, 1, 1}, -10).
{2018,12,22}

> uef_time:add_days({{2019, 1, 1}, {23, 59, 0}}, 10).
{{2019,1,11},{23,59,0}}

> uef_time:add_days({{2019, 1, 1}, {0, 1, 0}}, -10).
{{2018,12,22},{0,1,0}}

uef_time:add_weeks/1

uef_time:add_weeks(Weeks) -> NewDateTime.

Same as uef_time:add_seconds(Weeks * 604800). See docs of uef_time:add_seconds/1.

Types:

Weeks :: integer().
NewDateTime :: calendar:datetime().

uef_time:add_weeks/2

uef_time:add_weeks(DateOrDatetime, Weeks) -> NewDateOrDateTime.

Adds the number of weeks Weeks to DateOrDatetime and returns a new date or datetime value. The type of NewDateOrDateTime is the same as the type of DateOrDatetime.

Types:

DateOrDatetime :: calendar:date() | calendar:datetime().
Weeks :: integer().
NewDateOrDateTime :: calendar:date() | calendar:datetime().

Examples:

> uef_time:add_weeks({2019, 1, 1}, 4).
{2019,1,29}

> uef_time:add_weeks({2019, 1, 1}, -4).
{2018,12,4}

> uef_time:add_weeks({{2019, 1, 1}, {23, 59, 0}}, 4).
{{2019,1,29},{23,59,0}}

> uef_time:add_weeks({{2019, 1, 1}, {0, 1, 0}}, -4).
{{2018,12,4},{0,1,0}}

uef_time:add_months/1

uef_time:add_months(Months) -> NewDateTime.

Same as uef_time:add_months(erlang:localtime(), Months). See docs of uef_time:add_months/2.

Types:

Months :: integer().
NewDateTime :: calendar:datetime().

uef_time:add_months/2

uef_time:add_months(DateOrDatetime, Months) -> NewDateOrDateTime.

Adds the number of months Months to DateOrDatetime and returns a new date or datetime value. The type of NewDateOrDateTime is the same as the type of DateOrDatetime.

Types:

DateOrDatetime :: calendar:date() | calendar:datetime().
Months :: integer().
NewDateOrDateTime :: calendar:date() | calendar:datetime().

Examples:

> uef_time:add_months({2019, 1, 31}, 1).
{2019,2,28}

> uef_time:add_months({2016, 1, 31}, 1).
{2016,2,29}

> uef_time:add_months({2019, 1, 31}, -1).
{2018,12,31}

> uef_time:add_months({{2019, 1, 1}, {23, 59, 0}}, 1).
{{2019,2,1},{23,59,0}}

> uef_time:add_months({{2019, 1, 1}, {0, 1, 0}}, -1).
{{2018,12,1},{0,1,0}}

uef_time:add_years/1

uef_time:add_years(Years) -> NewDateTime.

Same as uef_time:add_years(erlang:localtime(), Years). See docs of uef_time:add_years/2.

Types:

Years :: integer().
NewDateTime :: calendar:datetime().

uef_time:add_years/2

uef_time:add_years(DateOrDatetime, Years) -> NewDateOrDateTime.

Adds the number of years Years to DateOrDatetime and returns a new date or datetime value. The type of NewDateOrDateTime is the same as the type of DateOrDatetime.

Types:

DateOrDatetime :: calendar:date() | calendar:datetime().
Years :: integer().
NewDateOrDateTime :: calendar:date() | calendar:datetime().

Examples:

> uef_time:add_years({2019, 1, 31}, 1).
{2020,1,31}

> uef_time:add_years({2019, 1, 31}, -1).
{2018,1,31}

> uef_time:add_years({{2019, 1, 1}, {23, 59, 0}}, 1).
{{2020,1,1},{23,59,0}}

> uef_time:add_years({{2019, 1, 1}, {0, 1, 0}}, -1).
{{2018,1,1},{0,1,0}}

uef_time:add_time/1

uef_time:add_time(Periods) -> NewDateTime.

Same as uef_time:add_time(erlang:localtime(), Periods). See docs of uef_time:add_time/2. NewDateTime is of type calendar:datetime(). See types for Periods in Types section of function uef_time:add_time/2.


uef_time:add_time/2

uef_time:add_time(DateOrDatetime, Periods) -> NewDateOrDateTime.

Adds one or more periods of time to DateOrDatetime and returns a new date or datetime value. This is a universal function based on functions uef_time:add_seconds/2, uef_time:add_minutes/2, uef_time:add_hours/2, uef_time:add_days/2, uef_time:add_weeks/2, uef_time:add_months/2 and uef_time:add_years/2. The type of NewDateOrDateTime depends on the type of DateOrDatetime and Periods (see Examples).

Types:

DateOrDatetime :: calendar:date() | calendar:datetime().
NewDateOrDateTime :: calendar:date() | calendar:datetime().

psecond() :: sec | second | seconds.
pminute() :: min | minute | minutes.
phour() :: hrs | hour | hours.
pday() :: day | days.
pmonth() :: month | months.
pyear() :: year | years.
ptype() :: psecond() | pminute() | phour() | pday() | pmonth() | pyear().

period() :: {integer(), ptype()} | {ptype(), integer()}.
periods() :: [period()].

Examples:

> uef_time:add_time({2000, 1, 1}, [{1, year}, {1, month}, {1, week}, {1, day}, {1, hour}, {1, minute}, {1, second}]).
{{2001,2,9},{1,1,1}}   % type calendar:datetime()

> uef_time:add_time({2000, 1, 1}, [{1, year}, {1, month}, {1, week}, {1, day}]).
{2001,2,9}   % type calendar:date()

> uef_time:add_time({{2000, 1, 1}, {0, 0, 0}}, [{1, year}, {1, month}, {1, week}, {1, day}]).
{{2001,2,9},{0,0,0}}   % type calendar:datetime()

> uef_time:add_time({2000, 1, 1}, [{year, 1}, {month, 1}, {week, 1}, {day, 1}, {hour, 1}, {minute, 1}, {second, 1}]).
{{2001,2,9},{1,1,1}}

> uef_time:add_time({2000, 1, 1}, [{1, hrs}, {1, min}, {1, sec}]).
{{2000,1,1},{1,1,1}}

> uef_time:add_time({{2000, 1, 31}, {23, 59, 59}}, [{1, hour}, {1, minute}, {1, second}]).
{{2000,2,1},{1,1,0}}

> uef_time:add_time({{2000, 1, 31}, {23, 59, 59}}, [{1, second}]).
{{2000,2,1},{0,0,0}}

> uef_time:add_time({2000, 1, 1}, [{1, years}]) =:= uef_time:add_years({2000, 1, 1}, 1).
true

> uef_time:add_time({2000, 1, 1}, [{1, month}]) =:= uef_time:add_months({2000, 1, 1}, 1).
true

uef_time:today/0

uef_time:today() -> CurrentDate.

Returns the current date as {Year, Month, Day}. Same as erlang:date(). CurrentDate is of type calendar:date().


uef_time:tomorrow/0

uef_time:tomorrow() -> TomorrowDate.

Returns tomorrow’s date as {Year, Month, Day}. TomorrowDate is of type calendar:date().


uef_time:yesterday/0

uef_time:yesterday() -> YesterdayDate.

Returns yesterday’s date as {Year, Month, Day}. YesterdayDate is of type calendar:date().


uef_time:unix_time/0

uef_time:unix_time() -> Seconds.

Returns the current number of seconds since 00:00:00 (UTC), 1 January 1970. It also known as Unix time or POSIX time or UNIX Epoch time.

Example:

> uef_time:unix_time().
1557670215

uef_time:unix_time/1

uef_time:unix_time(Datetime) -> Seconds.

Returns the number of seconds elapsed between 00:00:00 (UTC), 1 January 1970 and Datetime. Datetime must be of type calenadr:datetime().

Examples:

> uef_time:unix_time({{1970,1,1}, {0,0,0}}).
0

> uef_time:unix_time({{2000,1,1}, {23,59,59}}).
946771199

uef_time:days_diff/1

uef_time:days_diff(Date) -> Days.

Returns the difference in days between Date and the current local date provided by function erlang:date(). Date must be of type calendar:date() ({Year, Month, Day}). Days is a positive value if Date is after erlang:date() or a negative value otherwise.


uef_time:days_diff/2

uef_time:days_diff(Date1, Date2) -> Days.

Returns the difference in days between Date2 and Date1. Date1 and Date2 must be of type calendar:date() ({Year, Month, Day}). Days is a positive value if Date2 is after Date1 or a negative value otherwise.

Examples:

> uef_time:days_diff({1999, 1, 31}, {2019, 12, 31}).
7639

> uef_time:days_diff({2019, 12, 31}, {1999, 1, 31}).
-7639

uef_time:seconds_diff/1

uef_time:seconds_diff(DateTime) -> Seconds.

Returns the difference in seconds between Date and the current local time provided by function erlang:localtime(). DateTime must be of type calendar:datetime() ({{Year, Month, Day}, {Hour, Minute, Second}}). Seconds is a positive value if DateTime is after erlang:localtime() or a negative value otherwise.


uef_time:seconds_diff/2

uef_time:seconds_diff(DateTime1, DateTime2) -> Seconds.

Returns the difference in seconds between DateTime2 and DateTime1. DateTime1 and DateTime2 must be of type calendar:datetime() ({{Year, Month, Day}, {Hour, Minute, Second}}). Seconds is a positive value if DateTime2 is after DateTime1 or a negative value otherwise.

Examples:

> uef_time:seconds_diff({{1999, 1, 31}, {0, 0, 0}}, {{2019, 12, 31}, {0, 0, 0}}).
660009600

> uef_time:seconds_diff({{2019, 12, 31}, {0, 0, 0}}, {{1999, 1, 31}, {0, 0, 0}}).
-660009600

Build

Build with GNU make

make

Build with rebar3

rebar3 compile

Test and dialyze

Test/dialyze with GNU make

make test
make dialyzer
make xref
make cover

Test/dialyze with rebar3

rebar3 eunit
rebar3 dialyzer
rebar3 xref
rebar3 do eunit, cover

Build documentation

Build docs with GNU make

make docs

Build docs with rebar3

rebar3 edoc

Contributing

You are welcome :)