Package detail

uom

dividab4kMIT6.0.0

Extensible unit of measure conversion with type safety for typescript

readme

uom

npm version travis build Coverage Status code style: prettier MIT license

Extensible unit of measure conversion with type safety for typescript

Introduction

This package has functions to handle unit of measures. It works particulary well with typescript in which case it can provice some type safety for amounts of different quantity.

Installation

npm install --save uom

The library is compiled to ES5 and no polyfills are required.

NOTE: The base package uom does only contain the base SI units. In order to get more units to convert between you also need to install the uom-units package:

npm install --save uom-units

Features

Conversion

This feature allows you to convert amounts into different units.

import { Amount } from "uom";
import { Units } from "uom-units";

const amount = Amount.create(10, Units.Meter);
const inch = Amount.valueAs(Units.Inch, amount);

Extension (create your own unit)

A measure system has a number of BaseUnits which is used to create all other derived units in the system which are represented as ProductUnit or TransformedUnit. For example in the SI measure system, m and s are BaseUnitss and they can be used to create the m/s ProductUnit.

In the case that a derived unit can be known by a different name, an AlternateUnit can be used. For example in the SI system the derived unit N/m2 is also known as Pascal.

By using the base units you can create any unit.

import { Amount, Unit } from "uom";
import { Units } from "uom-units";

const myInchUnit = Unit.divideNumber(12.0, Units.Foot);
const amount = Amount.create(10, myInchUnit);
const meter = Amount.valueAs(Units.Meter, amount);

Type safety (typescript only)

By declaring your functions with a signature of typed Amount you can make sure the right type of amounts are inputs to the function.

import { Amount } from "uom";
import { Units } from "uom-units";

const length1 = Amount.create(10, Units.Meter);
const length2 = Amount.create(10, Units.Inch);
const volume1 = Amount.create(10, Units.CubicMeter);

const result = calculate(length1, length2); // OK
const result = calculate(volume1, length2); // Compile error

function calculate(Amount<Length> length1, Amount<Length> length2): Amount<Length> {
    return Amount.plus(length1, length2);
}

Formatting

Asosciating formatting directly with an Unit or Quantity is generally not a good idea. Formatting is application specific and should be implemented within application code. For example, an application may have air flows and water flows that both are of VolumeFlow quantity. In this case you may want separate labels and default units for air flow and water flow. Associating formatting directly with VolumeFlow or its units will not solve this. Instead, try tagging each VolumeFlow field within the application with either air_flow, or water_flow and provide different labels and default units per tag.

However if you are just building something smaller and want quick formatting, the [uo] package has some opinionated formatting that is directly associated with each Unit built-in. Specifically you can get the label and number of decimals for each unit.

However if you are just building something smaller and want quick formatting, this package has some opinionated formatting that is directly associated with each Unit built-in. Specifically you can get the label and number of decimals for each unit.

import { Amount, Format } from "uom";
import { Units } from "uom-units";

const length = Amount.create(10, Units.Meter);
const format = UnitFormat.getUnitFormat(length);
console.log(
  "The amount is " +
    Math.round(Amount.valueAs(Units.Inch, amount), format.decimalCount) +
    " " +
    format.label
);

There is also the buildDerivedSymbol() function which will derive a symbol for a unit by looking at which base units the unit was created:

import { Amount, Format } from "uom";
import { Units } from "uom-units";

const length = Amount.create(10, Units.MeterPerSecond);
const label = Unit.buildDerivedSymbol(length);
console.log(label); // m/s

Serialization

This feature can be used to serialize the units for persisting to/from for example a database.

import { Amount, Serialize } from "uom";
import { Units } from "uom-units";

const length = Amount.create(10, Units.Meter);
const serialized = Serialize.amountToString(length);
const deserialized = Serialize.stringToAmount(serialized);

API

The API is divided into modules, where each module contains functions that operate on a type that is exported from that module. For example the Amount module exports the type Amount.Amount and has functions like Amount.plus().

For more information, see the full API docs.

How to develop

Create a PR for addition or changes. Please update the changelog's "unreleased" section with your changes in your PR.

How to publish

Don't forget to update the changelog before publishing. Then run:

yarn version --patch
yarn version --minor
yarn version --major

Prior art

This library was inspired by JSR-275. See also this repo, this article. Altough JSR-275 was not accepted it evolved into JSR-363 which is now accepted.

changelog

Change Log

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog and this project adheres to Semantic Versioning.

Unreleased

Unreleased

  • Moved Format.getUnitsForQuantity to UnitMap.getUnitsForQuantity.
  • Moved Format.getUnitFormat to UnitFormat.getUnitFormat.
  • Removed extra paramter in UnitMap.getUnitsForQuantity.
  • Remove Format module.
  • Moved Unit.UnitMap to UnitMap.UnitMap.
  • Moved Unit.UnitLookup to UnitMap.UnitLookup.
  • Refactor tests, move to __tests__ folder

v5.0.0 - 2020-10-08

Changed

  • The consumer of the package is responsible for sending in a unit lookup function. See PR #51.

v4.1.0 - 2020-03-29

Added

  • Include typescript source from src/ in published npm package. See PR #50 for more info.

v4.0.0 - 2020-01-09

Changed

  • The consumer of the package is responsible for sending in units with the correct case. See issue #48 and PR #49.

v3.0.0 - 2019-11-05

Changed

  • All unit definitions (expect base SI units) moved to separate package uom-units.
  • Passing explicit UnitMap and UnitFormatMap is now required in Format and Serialize module functions.

v2.5.0 - 2019-11-01

Added

  • Added Units PoundLbPerSecond, GrainPerSecond, KilogramPerSquareMeterHour, GramPerSquareMeterHour, GramPerSquareMeterSecond, StandardCubicMeterPerHourPerSquareMeter, PoundLbPerSquareFeetHour, PoundLbPerSquareFeetSecond, GrainPerSquareFeetHour, GrainPerSquareFeetSecond, StandardCubicFootPerMinutePerSquareFeet.

v2.4.0 - 2019-10-17

Added

  • Added Units KiloJoulePerCubicMeter and BtuPerCubicFeet.

Changed

  • Format.getUnitsForQuantity() now accepts parameter for units. Default value is the registred units in this library.

v2.3.0 - 2019-04-09

Changed

  • Capitalize ACFM and ACFH labels

Added

  • Added Units StandardCubicFeetPerMinutePerSquareFeet and StandardCubicMeterPerHourPerSquareMeter.

v2.2.1 - 2019-03-06

Changed

  • Republish package because tags were out of sync.

v2.2.0 - 2019-03-06

Changed

  • All Amount compare functions now accepts a custom compare function as parameter.

v2.1.0 - 2019-01-10

Changed

  • Format module functions now takes an optional argument units map for application specific subset of units.

v2.0.0 - 2019-01-10

Added

  • Format module, see readme.
  • Serialize module, see readme.
  • Unit.buildDerivedSymbol().

Changed

  • Amount.toString() now uses buildDerivedSymbol instead of looking up the formatted label. This change was made to make Amount independent on the formatting data.

Removed

  • Some undocumented modules were removed (this functionality is partly documented in the added Format and Serialize modules):
    • unit-info.ts
    • unit-label.ts
    • unit-registry.ts

v1.0.0 - 2018-05-08

Added

  • Initial Release