Skip to content

UCUMConverterFormatter serializes seconds * 10^-5 weird #191

Description

@addict3d

I defined seconds * 10^-5 and it serializes weird.

I expected perhaps "s/100000" or "s.10^-5". The UCUMFormat'ers all produce "s.0".

Formatter output string
UCUM Case Insensitive "s.0"
UCUM Case Sensitive "s.0"
UCUM Print "s.0"
EBNFUnitFormat "s·10^-5"

Here is a test to recreate the potential issue.

package systems.uom.ucum.format;

import org.junit.jupiter.api.Test;
import tech.units.indriya.function.MultiplyConverter;

import javax.measure.Unit;
import javax.measure.format.UnitFormat;
import javax.measure.quantity.Time;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static systems.uom.ucum.UCUM.SECOND;
import static systems.uom.ucum.format.UCUMFormat.Variant.CASE_SENSITIVE;

public class UnitFormatWithNegativeExponentFactor {
    protected static final UnitFormat FORMAT_CS = UCUMFormat.getInstance(CASE_SENSITIVE);

    /**
     * s * 10^5 => pass
     */
    @Test
    public void testExponentFactor10e5() {
        MultiplyConverter e5 = MultiplyConverter.ofExponent(10, 5);
        Unit<Time> se5 = SECOND.transform(e5);
        assertEquals("s.100000", FORMAT_CS.format(se5));
    }

    /**
     * s * (1 / 10^5) => pass
     */
    @Test
    public void testRationalFactor10e5Reciprocal() {
        MultiplyConverter e5ReciprocalRational = MultiplyConverter.ofRational(1, 100000);

        Unit<Time> s_e5 = SECOND.transform(e5ReciprocalRational);
        assertEquals("s/100000", FORMAT_CS.format(s_e5));
    }

    /**
     * s * 10^-5 => fail
     * <p>
     * Expected :s/100000
     * Actual   :s.0
     */
    @Test
    public void testExponentFactor10e5Reciprocal() {
        MultiplyConverter e5ReciprocalPow10 = MultiplyConverter.ofExponent(10, -5);
        Unit<Time> se5 = SECOND.transform(e5ReciprocalPow10);
        assertEquals("s/100000", FORMAT_CS.format(se5));
    }
}

I'm not overly familiar with this ecosystem, but it strikes me that tech.units.indriya.AbstractUnit.prefix() always results in a PowerOfIntConverter via MultiplyConverter.ofPrefix() (same as MultiplyConverter.ofExponent()). Which by luck is how I constructed the unit I was using.

Should MultiplyConverter.ofPrefix() sometimes result in a RationalConverter instead? Or should additional logic be included in UCUMConverterFormatter.formatConverter()? It seems it already handles this scenario for RationalConverter.

If we can find a good path to resolve this, I'm happy to draft a PR. Cheers!

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions