Add digit_count and fraction_digit_count to RDF.Decimal

This commit is contained in:
Marcel Otto 2019-04-22 11:17:16 +02:00
parent 3de7d700d3
commit 568190e327
5 changed files with 84 additions and 1 deletions

View file

@ -10,6 +10,8 @@ This project adheres to [Semantic Versioning](http://semver.org/) and
### Added
- `RDF.Literal.matches?/3` for XQuery regex pattern matching
- `RDF.Decimal.digit_count/1` and `RDF.Decimal.fraction_digit_count/1` for
determining the number of digits of decimal literals
[Compare v0.6.0...HEAD](https://github.com/marcelotto/rdf-ex/compare/v0.6.0...HEAD)

View file

@ -8,6 +8,7 @@ defmodule RDF.Decimal do
alias Elixir.Decimal, as: D
@xsd_integer RDF.Datatype.NS.XSD.integer
@impl RDF.Datatype
def convert(value, opts)
@ -113,4 +114,37 @@ defmodule RDF.Decimal do
@impl RDF.Datatype
def compare(left, right), do: RDF.Numeric.compare(left, right)
@doc """
The number of digits in the XML Schema canonical form of the literal value.
"""
def digit_count(%RDF.Literal{datatype: @id} = literal) do
if valid?(literal) do
literal
|> canonical()
|> lexical()
|> String.replace(".", "")
|> String.replace("-", "")
|> String.length()
end
end
def digit_count(%RDF.Literal{datatype: @xsd_integer} = literal),
do: RDF.Integer.digit_count(literal)
@doc """
The number of digits to the right of the decimal point in the XML Schema canonical form of the literal value.
"""
def fraction_digit_count(%RDF.Literal{datatype: @id, value: value} = literal) do
if valid?(literal) do
[_, fraction] =
literal
|> canonical()
|> lexical()
|> String.split(".")
String.length(fraction)
end
end
def fraction_digit_count(%RDF.Literal{datatype: @xsd_integer}), do: 0
end

View file

@ -73,4 +73,18 @@ defmodule RDF.Integer do
@impl RDF.Datatype
def compare(left, right), do: RDF.Numeric.compare(left, right)
@doc """
The number of digits in the XML Schema canonical form of the literal value.
"""
def digit_count(%RDF.Literal{datatype: @id} = literal) do
if valid?(literal) do
literal
|> canonical()
|> lexical()
|> String.replace("-", "")
|> String.length()
end
end
end

View file

@ -122,6 +122,32 @@ defmodule RDF.DecimalTest do
end
end
test "digit_count/1" do
assert RDF.Decimal.digit_count(RDF.decimal("1.2345")) == 5
assert RDF.Decimal.digit_count(RDF.decimal("-1.2345")) == 5
assert RDF.Decimal.digit_count(RDF.decimal("+1.2345")) == 5
assert RDF.Decimal.digit_count(RDF.decimal("01.23450")) == 5
assert RDF.Decimal.digit_count(RDF.decimal("01.23450")) == 5
assert RDF.Decimal.digit_count(RDF.decimal("NAN")) == nil
assert RDF.Decimal.digit_count(RDF.integer("2")) == 1
assert RDF.Decimal.digit_count(RDF.integer("23")) == 2
assert RDF.Decimal.digit_count(RDF.integer("023")) == 2
end
test "fraction_digit_count/1" do
assert RDF.Decimal.fraction_digit_count(RDF.decimal("1.2345")) == 4
assert RDF.Decimal.fraction_digit_count(RDF.decimal("-1.2345")) == 4
assert RDF.Decimal.fraction_digit_count(RDF.decimal("+1.2345")) == 4
assert RDF.Decimal.fraction_digit_count(RDF.decimal("01.23450")) == 4
assert RDF.Decimal.fraction_digit_count(RDF.decimal("0.023450")) == 5
assert RDF.Decimal.fraction_digit_count(RDF.decimal("NAN")) == nil
assert RDF.Decimal.fraction_digit_count(RDF.integer("2")) == 0
assert RDF.Decimal.fraction_digit_count(RDF.integer("23")) == 0
assert RDF.Decimal.fraction_digit_count(RDF.integer("023")) == 0
end
defmacrop sigil_d(str, _opts) do
quote do
@ -151,5 +177,4 @@ defmodule RDF.DecimalTest do
assert Decimal.canonical_decimal(~d"1.2E3") == ~d"1200.0"
assert Decimal.canonical_decimal(~d"-42E+3") == ~d"-42000.0"
end
end

View file

@ -76,6 +76,14 @@ defmodule RDF.IntegerTest do
end
end
test "digit_count/1" do
assert RDF.Integer.digit_count(RDF.integer("2")) == 1
assert RDF.Integer.digit_count(RDF.integer("23")) == 2
assert RDF.Integer.digit_count(RDF.integer("023")) == 2
assert RDF.Integer.digit_count(RDF.integer("+023")) == 2
assert RDF.Integer.digit_count(RDF.integer("-023")) == 2
assert RDF.Integer.digit_count(RDF.integer("NaN")) == nil
end
describe "equality" do
test "two literals are equal when they have the same datatype and lexical form" do