Repository files navigation

JS-quantities

Build Status

JS-quantities is originally a JavaScript port of Kevin Olbrich's library Ruby Units (http://github.com/olbrich/ruby-units).

The library aims to simplify the handling of units for scientific calculations involving quantities.

JS-quantities is built as UMD and ES modules and can be used with Node.js and browsers. It has no dependencies.

Installation

Install with npm install js-quantities or download latest release v1.7.5 as:

Usage

Node.js

// As CommonJS module
const Qty = require('js-quantities');
// As ES module
import Qty from 'js-quantities/esm';

Browsers

  • UMD module could be included as is:
<scriptsrc='quantities.js'></script>

In this case, it will define a global variable Qty.

define(['quantities'],function(Qty){
...
});

Synopsis

Creation

Instances of quantities are made by means of Qty() method. Qty can both be used as a constructor (with new) or as a factory (without new):

qty=newQty('23 ft');// constructorqty=Qty('23 ft');// factory

Qty constructor accepts strings, numbers and Qty instances as initializing values.

If scalars and their respective units are available programmatically, the two argument signature may be useful:

qty=newQty(124,'cm');// => 1.24 meterqty=Qty(124,'cm');// => 1.24 meter

For the sake of simplicity, one will use the factory way below but using new Qty() is equivalent.

qty=Qty('1m');// => 1 meterqty=Qty('m');// => 1 meter (scalar defaults to 1)qty=Qty('1 N*m');qty=Qty('1 N m');// * is optionalqty=Qty('1 m/s');qty=Qty('1 m^2/s^2');qty=Qty('1 m^2 s^-2');// negative powersqty=Qty('1 m2 s-2');// ^ is optionalqty=Qty('1 m^2 kg^2 J^2/s^2 A');qty=Qty('1.5');// unitless quantityqty=Qty(1.5);// number as initializing valueqty=Qty('1 attoparsec/microfortnight');qtyCopy=Qty(qty);// quantity could be copied when used as// initializing value

Qty.parse utility method is also provided to parse and create quantities from strings. Unlike the constructor, it will return null instead of throwing an error when parsing an invalid quantity.

Qty.parse('1 m');// => 1 meterQty.parse('foo')// => null

Available well-known kinds

Qty.getKinds();// => Array of names of every well-known kind of units

Available units of a particular kind

Qty.getUnits('currency');// => [ 'dollar', 'cents' ]// Or all alphabetically sortedQty.getUnits();// => [ 'acre','Ah','ampere','AMU','angstrom']

Alternative names of a unit

Qty.getAliases('m');// => [ 'm', 'meter', 'meters', 'metre', 'metres' ]

Quantity compatibility, kind and various queries

qty1.isCompatible(qty2);// => true or falseqty.kind();// => 'length', 'area', etc...qty.isUnitless();// => true or falseqty.isBase();// => true if quantity is represented with base units

Conversion

qty.toBase();// converts to SI units (10 cm => 0.1 m) (new instance)qty.toFloat();// returns scalar of unitless quantity// (otherwise throws error)qty.to('m');// converts quantity to meter if compatible// or throws an error (new instance)qty1.to(qty2);// converts quantity to same unit of qty2 if compatible// or throws an error (new instance)qty.inverse();// converts quantity to its inverse// ('100 m/s' => '.01 s/m')// Inverses can be used, but there is no special checking to// rename the unitsQty('10ohm').inverse()// '.1/ohm'// (not '.1S', although they are equivalent)// however, the 'to' command will convert between inverses alsoQty('10ohm').to('S')// '.1S'

Qty.swiftConverter() is a fast way to efficiently convert large array of Number values. It configures a function accepting a value or an array of Number values to convert.

varconvert=Qty.swiftConverter('m/h','ft/s');// Configures converter// Converting single valuevarconverted=convert(2500);// => 2.278..// Converting large array of valuesvarconvertedSerie=convert([2500,5000, ...]);// => [2.278.., 4.556.., ...]

The main drawback of this conversion method is that it does not take care of rounding issues.

Comparison

qty1.eq(qty2);// => true if both quantities are equal (1m == 100cm => true)qty1.same(qty2);// => true if both quantities are same (1m == 100cm => false)qty1.lt(qty2);// => true if qty1 is stricty less than qty2qty1.lte(qty2);// => true if qty1 is less than or equal to qty2qty1.gt(qty2);// => true if qty1 is stricty greater than qty2qty1.gte(qty2);// => true if qty1 is greater than or equal to qty2qty1.compareTo(qty2);// => -1 if qty1 < qty2,// => 0 if qty1 == qty2,// => 1 if qty1 > qty2

Operators

  • add(other): Add. other can be string or quantity. other should be unit compatible.
  • sub(other): Substract. other can be string or quantity. other should be unit compatible.
  • mul(other): Multiply. other can be string, number or quantity.
  • div(other): Divide. other can be string, number or quantity.

Rounding

Qty#toPrec(precision) : returns the nearest multiple of quantity passed as precision.

varqty=Qty('5.17 ft');qty.toPrec('ft');// => 5 ftqty.toPrec('0.5 ft');// => 5 ftqty.toPrec('0.25 ft');// => 5.25 ftqty.toPrec('0.1 ft');// => 5.2 ftqty.toPrec('0.05 ft');// => 5.15 ftqty.toPrec('0.01 ft');// => 5.17 ftqty.toPrec('0.00001 ft');// => 5.17 ftqty.toPrec('2 ft');// => 6 ftqty.toPrec('2');// => 6 ftvarqty=Qty('6.3782 m');qty.toPrec('dm');// => 6.4 mqty.toPrec('cm');// => 6.38 mqty.toPrec('mm');// => 6.378 mqty.toPrec('5 cm');// => 6.4 mqty.toPrec('10 m');// => 10 mqty.toPrec(0.1);// => 6.3 mvarqty=Qty('1.146 MPa');qty.toPrec('0.1 bar');// => 1.15 MPa

Formatting quantities

Qty#toString returns a string using the canonical form of the quantity (that is it could be seamlessly reparsed by Qty).

varqty=Qty('1.146 MPa');qty.toString();// => '1.146 MPa'

As a shorthand, units could be passed to Qty#toString and is equivalent to successively call Qty#to then Qty#toString.

varqty=Qty('1.146 MPa');qty.toString('bar');// => '11.46 bar'qty.to('bar').toString();// => '11.46 bar'

Qty#toString could also be used with any method from Qty to make some sort of formatting. For instance, one could use Qty#toPrec to fix the maximum number of decimals:

varqty=Qty('1.146 MPa');qty.toPrec(0.1).toString();// => '1.1 MPa'qty.to('bar').toPrec(0.1).toString();// => '11.5 bar'

For advanced formatting needs as localization, specific rounding or any other custom customization, quantities can be transformed into strings through Qty#format according to optional target units and formatter. If target units are specified, the quantity is converted into them before formatting.

Such a string is not intended to be reparsed to construct a new instance of Qty (unlike output of Qty#toString).

If no formatter is specified, quantities are formatted according to default js-quantities' formatter and is equivalent to Qty#toString.

varqty=Qty('1.1234 m');qty.format();// same units, default formatter => '1.234 m'qty.format('cm');// converted to 'cm', default formatter => '123.45 cm'

Qty#format could delegates formatting to a custom formatter if required. A formatter is a callback function accepting scalar and units as parameters and returning a formatted string representing the quantity.

varconfigurableRoundingFormatter=function(maxDecimals){returnfunction(scalar,units){varpow=Math.pow(10,maxDecimals);varrounded=Math.round(scalar*pow)/pow;returnrounded+' '+units;};};varqty=Qty('1.1234 m');// same units, custom formatter => '1.12 m'qty.format(configurableRoundingFormatter(2));// convert to 'cm', custom formatter => '123.4 cm'qty.format('cm',configurableRoundingFormatter(1));

Custom formatter can be configured globally by setting Qty.formatter.

Qty.formatter=configurableRoundingFormatter(2);varqty=Qty('1.1234 m');qty.format();// same units, current default formatter => '1.12 m'

Temperatures

Like ruby-units, JS-quantities makes a distinction between a temperature (which technically is a property) and degrees of temperature (which temperatures are measured in).

Temperature units (i.e., 'tempK') can be converted back and forth, and will take into account the differences in the zero points of the various scales. Differential temperature (e.g., '100 degC') units behave like most other units.

Qty('37 tempC').to('tempF')// => 98.6 tempF

JS-quantities will throw an error if you attempt to create a temperature unit that would fall below absolute zero.

Unit math on temperatures is fairly limited.

Qty('100 tempC').add('10 degC')// 110 tempCQty('100 tempC').sub('10 degC')// 90 tempCQty('100 tempC').add('50 tempC')// throws errorQty('100 tempC').sub('50 tempC')// 50 degCQty('50 tempC').sub('100 tempC')// -50 degCQty('100 tempC').mul(scalar)// 100*scalar tempCQty('100 tempC').div(scalar)// 100/scalar tempCQty('100 tempC').mul(qty)// throws errorQty('100 tempC').div(qty)// throws errorQty('100 tempC*unit')// throws errorQty('100 tempC/unit')// throws errorQty('100 unit/tempC')// throws errorQty('100 tempC').inverse()// throws error
Qty('100 tempC').to('degC')// => 100 degC

This conversion references the 0 point on the scale of the temperature unit

Qty('100 degC').to('tempC')// => -173.15 tempC

These conversions are always interpreted as being relative to absolute zero. Conversions are probably better done like this...

Qty('0 tempC').add('100 degC')// => 100 tempC

Errors

Every error thrown by JS-quantities is an instance of Qty.Error.

try{// code triggering an error inside JS-quantities}catch(e){if(einstanceofQty.Error){// ...}else{// ...}}

Tests

Tests are implemented with Jasmine (https://github.com/pivotal/jasmine). You could use both HTML and jasmine-node runners.

To execute specs through HTML runner, just open SpecRunner.html file in a browser to execute them.

To execute specs through jasmine-node, launch:

make test

Performance regression test

There is a small benchmarking HTML page to spot performance regression between currently checked-out quantities.js and any committed version. Just execute:

make bench

then open http://0.0.0.0:3000/bench

Checked-out version is benchmarked against HEAD by default but it could be changed by passing any commit SHA on the command line. Port (default 3000) is also configurable.

make bench COMMIT=e0c7fc468 PORT=5000

TypeScript type declarations

A TypeScript declaration file is published on DefinitelyTyped.

It could be installed with npm install @types/js-quantities.

Contribute

Feedback and contributions are welcomed.

Pull requests must pass tests and linting. Please make sure that make test and make lint return no errors before submitting.

About

JavaScript library for quantity calculation and unit conversion

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

JS-quantities

Build Status

JS-quantities is originally a JavaScript port of Kevin Olbrich's library Ruby Units (http://github.com/olbrich/ruby-units).

The library aims to simplify the handling of units for scientific calculations involving quantities.

JS-quantities is built as UMD and ES modules and can be used with Node.js and browsers. It has no dependencies.

Installation

Install with npm install js-quantities or download latest release v1.7.5 as:

Usage

Node.js

// As CommonJS module
const Qty = require('js-quantities');
// As ES module
import Qty from 'js-quantities/esm';

Browsers

  • UMD module could be included as is:
<scriptsrc='quantities.js'></script>

In this case, it will define a global variable Qty.

define(['quantities'],function(Qty){
...
});

Synopsis

Creation

Instances of quantities are made by means of Qty() method. Qty can both be used as a constructor (with new) or as a factory (without new):

qty=newQty('23 ft');// constructorqty=Qty('23 ft');// factory

Qty constructor accepts strings, numbers and Qty instances as initializing values.

If scalars and their respective units are available programmatically, the two argument signature may be useful:

qty=newQty(124,'cm');// => 1.24 meterqty=Qty(124,'cm');// => 1.24 meter

For the sake of simplicity, one will use the factory way below but using new Qty() is equivalent.

qty=Qty('1m');// => 1 meterqty=Qty('m');// => 1 meter (scalar defaults to 1)qty=Qty('1 N*m');qty=Qty('1 N m');// * is optionalqty=Qty('1 m/s');qty=Qty('1 m^2/s^2');qty=Qty('1 m^2 s^-2');// negative powersqty=Qty('1 m2 s-2');// ^ is optionalqty=Qty('1 m^2 kg^2 J^2/s^2 A');qty=Qty('1.5');// unitless quantityqty=Qty(1.5);// number as initializing valueqty=Qty('1 attoparsec/microfortnight');qtyCopy=Qty(qty);// quantity could be copied when used as// initializing value

Qty.parse utility method is also provided to parse and create quantities from strings. Unlike the constructor, it will return null instead of throwing an error when parsing an invalid quantity.

Qty.parse('1 m');// => 1 meterQty.parse('foo')// => null

Available well-known kinds

Qty.getKinds();// => Array of names of every well-known kind of units

Available units of a particular kind

Qty.getUnits('currency');// => [ 'dollar', 'cents' ]// Or all alphabetically sortedQty.getUnits();// => [ 'acre','Ah','ampere','AMU','angstrom']

Alternative names of a unit

Qty.getAliases('m');// => [ 'm', 'meter', 'meters', 'metre', 'metres' ]

Quantity compatibility, kind and various queries

qty1.isCompatible(qty2);// => true or falseqty.kind();// => 'length', 'area', etc...qty.isUnitless();// => true or falseqty.isBase();// => true if quantity is represented with base units

Conversion

qty.toBase();// converts to SI units (10 cm => 0.1 m) (new instance)qty.toFloat();// returns scalar of unitless quantity// (otherwise throws error)qty.to('m');// converts quantity to meter if compatible// or throws an error (new instance)qty1.to(qty2);// converts quantity to same unit of qty2 if compatible// or throws an error (new instance)qty.inverse();// converts quantity to its inverse// ('100 m/s' => '.01 s/m')// Inverses can be used, but there is no special checking to// rename the unitsQty('10ohm').inverse()// '.1/ohm'// (not '.1S', although they are equivalent)// however, the 'to' command will convert between inverses alsoQty('10ohm').to('S')// '.1S'

Qty.swiftConverter() is a fast way to efficiently convert large array of Number values. It configures a function accepting a value or an array of Number values to convert.

varconvert=Qty.swiftConverter('m/h','ft/s');// Configures converter// Converting single valuevarconverted=convert(2500);// => 2.278..// Converting large array of valuesvarconvertedSerie=convert([2500,5000, ...]);// => [2.278.., 4.556.., ...]

The main drawback of this conversion method is that it does not take care of rounding issues.

Comparison

qty1.eq(qty2);// => true if both quantities are equal (1m == 100cm => true)qty1.same(qty2);// => true if both quantities are same (1m == 100cm => false)qty1.lt(qty2);// => true if qty1 is stricty less than qty2qty1.lte(qty2);// => true if qty1 is less than or equal to qty2qty1.gt(qty2);// => true if qty1 is stricty greater than qty2qty1.gte(qty2);// => true if qty1 is greater than or equal to qty2qty1.compareTo(qty2);// => -1 if qty1 < qty2,// => 0 if qty1 == qty2,// => 1 if qty1 > qty2

Operators

  • add(other): Add. other can be string or quantity. other should be unit compatible.
  • sub(other): Substract. other can be string or quantity. other should be unit compatible.
  • mul(other): Multiply. other can be string, number or quantity.
  • div(other): Divide. other can be string, number or quantity.

Rounding

Qty#toPrec(precision) : returns the nearest multiple of quantity passed as precision.

varqty=Qty('5.17 ft');qty.toPrec('ft');// => 5 ftqty.toPrec('0.5 ft');// => 5 ftqty.toPrec('0.25 ft');// => 5.25 ftqty.toPrec('0.1 ft');// => 5.2 ftqty.toPrec('0.05 ft');// => 5.15 ftqty.toPrec('0.01 ft');// => 5.17 ftqty.toPrec('0.00001 ft');// => 5.17 ftqty.toPrec('2 ft');// => 6 ftqty.toPrec('2');// => 6 ftvarqty=Qty('6.3782 m');qty.toPrec('dm');// => 6.4 mqty.toPrec('cm');// => 6.38 mqty.toPrec('mm');// => 6.378 mqty.toPrec('5 cm');// => 6.4 mqty.toPrec('10 m');// => 10 mqty.toPrec(0.1);// => 6.3 mvarqty=Qty('1.146 MPa');qty.toPrec('0.1 bar');// => 1.15 MPa

Formatting quantities

Qty#toString returns a string using the canonical form of the quantity (that is it could be seamlessly reparsed by Qty).

varqty=Qty('1.146 MPa');qty.toString();// => '1.146 MPa'

As a shorthand, units could be passed to Qty#toString and is equivalent to successively call Qty#to then Qty#toString.

varqty=Qty('1.146 MPa');qty.toString('bar');// => '11.46 bar'qty.to('bar').toString();// => '11.46 bar'

Qty#toString could also be used with any method from Qty to make some sort of formatting. For instance, one could use Qty#toPrec to fix the maximum number of decimals:

varqty=Qty('1.146 MPa');qty.toPrec(0.1).toString();// => '1.1 MPa'qty.to('bar').toPrec(0.1).toString();// => '11.5 bar'

For advanced formatting needs as localization, specific rounding or any other custom customization, quantities can be transformed into strings through Qty#format according to optional target units and formatter. If target units are specified, the quantity is converted into them before formatting.

Such a string is not intended to be reparsed to construct a new instance of Qty (unlike output of Qty#toString).

If no formatter is specified, quantities are formatted according to default js-quantities' formatter and is equivalent to Qty#toString.

varqty=Qty('1.1234 m');qty.format();// same units, default formatter => '1.234 m'qty.format('cm');// converted to 'cm', default formatter => '123.45 cm'

Qty#format could delegates formatting to a custom formatter if required. A formatter is a callback function accepting scalar and units as parameters and returning a formatted string representing the quantity.

varconfigurableRoundingFormatter=function(maxDecimals){returnfunction(scalar,units){varpow=Math.pow(10,maxDecimals);varrounded=Math.round(scalar*pow)/pow;returnrounded+' '+units;};};varqty=Qty('1.1234 m');// same units, custom formatter => '1.12 m'qty.format(configurableRoundingFormatter(2));// convert to 'cm', custom formatter => '123.4 cm'qty.format('cm',configurableRoundingFormatter(1));

Custom formatter can be configured globally by setting Qty.formatter.

Qty.formatter=configurableRoundingFormatter(2);varqty=Qty('1.1234 m');qty.format();// same units, current default formatter => '1.12 m'

Temperatures

Like ruby-units, JS-quantities makes a distinction between a temperature (which technically is a property) and degrees of temperature (which temperatures are measured in).

Temperature units (i.e., 'tempK') can be converted back and forth, and will take into account the differences in the zero points of the various scales. Differential temperature (e.g., '100 degC') units behave like most other units.

Qty('37 tempC').to('tempF')// => 98.6 tempF

JS-quantities will throw an error if you attempt to create a temperature unit that would fall below absolute zero.

Unit math on temperatures is fairly limited.

Qty('100 tempC').add('10 degC')// 110 tempCQty('100 tempC').sub('10 degC')// 90 tempCQty('100 tempC').add('50 tempC')// throws errorQty('100 tempC').sub('50 tempC')// 50 degCQty('50 tempC').sub('100 tempC')// -50 degCQty('100 tempC').mul(scalar)// 100*scalar tempCQty('100 tempC').div(scalar)// 100/scalar tempCQty('100 tempC').mul(qty)// throws errorQty('100 tempC').div(qty)// throws errorQty('100 tempC*unit')// throws errorQty('100 tempC/unit')// throws errorQty('100 unit/tempC')// throws errorQty('100 tempC').inverse()// throws error
Qty('100 tempC').to('degC')// => 100 degC

This conversion references the 0 point on the scale of the temperature unit

Qty('100 degC').to('tempC')// => -173.15 tempC

These conversions are always interpreted as being relative to absolute zero. Conversions are probably better done like this...

Qty('0 tempC').add('100 degC')// => 100 tempC

Errors

Every error thrown by JS-quantities is an instance of Qty.Error.

try{// code triggering an error inside JS-quantities}catch(e){if(einstanceofQty.Error){// ...}else{// ...}}

Tests

Tests are implemented with Jasmine (https://github.com/pivotal/jasmine). You could use both HTML and jasmine-node runners.

To execute specs through HTML runner, just open SpecRunner.html file in a browser to execute them.

To execute specs through jasmine-node, launch:

make test

Performance regression test

There is a small benchmarking HTML page to spot performance regression between currently checked-out quantities.js and any committed version. Just execute:

make bench

then open http://0.0.0.0:3000/bench

Checked-out version is benchmarked against HEAD by default but it could be changed by passing any commit SHA on the command line. Port (default 3000) is also configurable.

make bench COMMIT=e0c7fc468 PORT=5000

TypeScript type declarations

A TypeScript declaration file is published on DefinitelyTyped.

It could be installed with npm install @types/js-quantities.

Contribute

Feedback and contributions are welcomed.

Pull requests must pass tests and linting. Please make sure that make test and make lint return no errors before submitting.

About

JavaScript library for quantity calculation and unit conversion

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

JS-quantities

Build Status

JS-quantities is originally a JavaScript port of Kevin Olbrich's library Ruby Units (http://github.com/olbrich/ruby-units).

The library aims to simplify the handling of units for scientific calculations involving quantities.

JS-quantities is built as UMD and ES modules and can be used with Node.js and browsers. It has no dependencies.

Installation

Install with npm install js-quantities or download latest release v1.7.5 as:

Usage

Node.js

// As CommonJS module
const Qty = require('js-quantities');
// As ES module
import Qty from 'js-quantities/esm';

Browsers

  • UMD module could be included as is:
<scriptsrc='quantities.js'></script>

In this case, it will define a global variable Qty.

define(['quantities'],function(Qty){
...
});

Synopsis

Creation

Instances of quantities are made by means of Qty() method. Qty can both be used as a constructor (with new) or as a factory (without new):

qty=newQty('23 ft');// constructorqty=Qty('23 ft');// factory

Qty constructor accepts strings, numbers and Qty instances as initializing values.

If scalars and their respective units are available programmatically, the two argument signature may be useful:

qty=newQty(124,'cm');// => 1.24 meterqty=Qty(124,'cm');// => 1.24 meter

For the sake of simplicity, one will use the factory way below but using new Qty() is equivalent.

qty=Qty('1m');// => 1 meterqty=Qty('m');// => 1 meter (scalar defaults to 1)qty=Qty('1 N*m');qty=Qty('1 N m');// * is optionalqty=Qty('1 m/s');qty=Qty('1 m^2/s^2');qty=Qty('1 m^2 s^-2');// negative powersqty=Qty('1 m2 s-2');// ^ is optionalqty=Qty('1 m^2 kg^2 J^2/s^2 A');qty=Qty('1.5');// unitless quantityqty=Qty(1.5);// number as initializing valueqty=Qty('1 attoparsec/microfortnight');qtyCopy=Qty(qty);// quantity could be copied when used as// initializing value

Qty.parse utility method is also provided to parse and create quantities from strings. Unlike the constructor, it will return null instead of throwing an error when parsing an invalid quantity.

Qty.parse('1 m');// => 1 meterQty.parse('foo')// => null

Available well-known kinds

Qty.getKinds();// => Array of names of every well-known kind of units

Available units of a particular kind

Qty.getUnits('currency');// => [ 'dollar', 'cents' ]// Or all alphabetically sortedQty.getUnits();// => [ 'acre','Ah','ampere','AMU','angstrom']

Alternative names of a unit

Qty.getAliases('m');// => [ 'm', 'meter', 'meters', 'metre', 'metres' ]

Quantity compatibility, kind and various queries

qty1.isCompatible(qty2);// => true or falseqty.kind();// => 'length', 'area', etc...qty.isUnitless();// => true or falseqty.isBase();// => true if quantity is represented with base units

Conversion

qty.toBase();// converts to SI units (10 cm => 0.1 m) (new instance)qty.toFloat();// returns scalar of unitless quantity// (otherwise throws error)qty.to('m');// converts quantity to meter if compatible// or throws an error (new instance)qty1.to(qty2);// converts quantity to same unit of qty2 if compatible// or throws an error (new instance)qty.inverse();// converts quantity to its inverse// ('100 m/s' => '.01 s/m')// Inverses can be used, but there is no special checking to// rename the unitsQty('10ohm').inverse()// '.1/ohm'// (not '.1S', although they are equivalent)// however, the 'to' command will convert between inverses alsoQty('10ohm').to('S')// '.1S'

Qty.swiftConverter() is a fast way to efficiently convert large array of Number values. It configures a function accepting a value or an array of Number values to convert.

varconvert=Qty.swiftConverter('m/h','ft/s');// Configures converter// Converting single valuevarconverted=convert(2500);// => 2.278..// Converting large array of valuesvarconvertedSerie=convert([2500,5000, ...]);// => [2.278.., 4.556.., ...]

The main drawback of this conversion method is that it does not take care of rounding issues.

Comparison

qty1.eq(qty2);// => true if both quantities are equal (1m == 100cm => true)qty1.same(qty2);// => true if both quantities are same (1m == 100cm => false)qty1.lt(qty2);// => true if qty1 is stricty less than qty2qty1.lte(qty2);// => true if qty1 is less than or equal to qty2qty1.gt(qty2);// => true if qty1 is stricty greater than qty2qty1.gte(qty2);// => true if qty1 is greater than or equal to qty2qty1.compareTo(qty2);// => -1 if qty1 < qty2,// => 0 if qty1 == qty2,// => 1 if qty1 > qty2

Operators

  • add(other): Add. other can be string or quantity. other should be unit compatible.
  • sub(other): Substract. other can be string or quantity. other should be unit compatible.
  • mul(other): Multiply. other can be string, number or quantity.
  • div(other): Divide. other can be string, number or quantity.

Rounding

Qty#toPrec(precision) : returns the nearest multiple of quantity passed as precision.

varqty=Qty('5.17 ft');qty.toPrec('ft');// => 5 ftqty.toPrec('0.5 ft');// => 5 ftqty.toPrec('0.25 ft');// => 5.25 ftqty.toPrec('0.1 ft');// => 5.2 ftqty.toPrec('0.05 ft');// => 5.15 ftqty.toPrec('0.01 ft');// => 5.17 ftqty.toPrec('0.00001 ft');// => 5.17 ftqty.toPrec('2 ft');// => 6 ftqty.toPrec('2');// => 6 ftvarqty=Qty('6.3782 m');qty.toPrec('dm');// => 6.4 mqty.toPrec('cm');// => 6.38 mqty.toPrec('mm');// => 6.378 mqty.toPrec('5 cm');// => 6.4 mqty.toPrec('10 m');// => 10 mqty.toPrec(0.1);// => 6.3 mvarqty=Qty('1.146 MPa');qty.toPrec('0.1 bar');// => 1.15 MPa

Formatting quantities

Qty#toString returns a string using the canonical form of the quantity (that is it could be seamlessly reparsed by Qty).

varqty=Qty('1.146 MPa');qty.toString();// => '1.146 MPa'

As a shorthand, units could be passed to Qty#toString and is equivalent to successively call Qty#to then Qty#toString.

varqty=Qty('1.146 MPa');qty.toString('bar');// => '11.46 bar'qty.to('bar').toString();// => '11.46 bar'

Qty#toString could also be used with any method from Qty to make some sort of formatting. For instance, one could use Qty#toPrec to fix the maximum number of decimals:

varqty=Qty('1.146 MPa');qty.toPrec(0.1).toString();// => '1.1 MPa'qty.to('bar').toPrec(0.1).toString();// => '11.5 bar'

For advanced formatting needs as localization, specific rounding or any other custom customization, quantities can be transformed into strings through Qty#format according to optional target units and formatter. If target units are specified, the quantity is converted into them before formatting.

Such a string is not intended to be reparsed to construct a new instance of Qty (unlike output of Qty#toString).

If no formatter is specified, quantities are formatted according to default js-quantities' formatter and is equivalent to Qty#toString.

varqty=Qty('1.1234 m');qty.format();// same units, default formatter => '1.234 m'qty.format('cm');// converted to 'cm', default formatter => '123.45 cm'

Qty#format could delegates formatting to a custom formatter if required. A formatter is a callback function accepting scalar and units as parameters and returning a formatted string representing the quantity.

varconfigurableRoundingFormatter=function(maxDecimals){returnfunction(scalar,units){varpow=Math.pow(10,maxDecimals);varrounded=Math.round(scalar*pow)/pow;returnrounded+' '+units;};};varqty=Qty('1.1234 m');// same units, custom formatter => '1.12 m'qty.format(configurableRoundingFormatter(2));// convert to 'cm', custom formatter => '123.4 cm'qty.format('cm',configurableRoundingFormatter(1));

Custom formatter can be configured globally by setting Qty.formatter.

Qty.formatter=configurableRoundingFormatter(2);varqty=Qty('1.1234 m');qty.format();// same units, current default formatter => '1.12 m'

Temperatures

Like ruby-units, JS-quantities makes a distinction between a temperature (which technically is a property) and degrees of temperature (which temperatures are measured in).

Temperature units (i.e., 'tempK') can be converted back and forth, and will take into account the differences in the zero points of the various scales. Differential temperature (e.g., '100 degC') units behave like most other units.

Qty('37 tempC').to('tempF')// => 98.6 tempF

JS-quantities will throw an error if you attempt to create a temperature unit that would fall below absolute zero.

Unit math on temperatures is fairly limited.

Qty('100 tempC').add('10 degC')// 110 tempCQty('100 tempC').sub('10 degC')// 90 tempCQty('100 tempC').add('50 tempC')// throws errorQty('100 tempC').sub('50 tempC')// 50 degCQty('50 tempC').sub('100 tempC')// -50 degCQty('100 tempC').mul(scalar)// 100*scalar tempCQty('100 tempC').div(scalar)// 100/scalar tempCQty('100 tempC').mul(qty)// throws errorQty('100 tempC').div(qty)// throws errorQty('100 tempC*unit')// throws errorQty('100 tempC/unit')// throws errorQty('100 unit/tempC')// throws errorQty('100 tempC').inverse()// throws error
Qty('100 tempC').to('degC')// => 100 degC

This conversion references the 0 point on the scale of the temperature unit

Qty('100 degC').to('tempC')// => -173.15 tempC

These conversions are always interpreted as being relative to absolute zero. Conversions are probably better done like this...

Qty('0 tempC').add('100 degC')// => 100 tempC

Errors

Every error thrown by JS-quantities is an instance of Qty.Error.

try{// code triggering an error inside JS-quantities}catch(e){if(einstanceofQty.Error){// ...}else{// ...}}

Tests

Tests are implemented with Jasmine (https://github.com/pivotal/jasmine). You could use both HTML and jasmine-node runners.

To execute specs through HTML runner, just open SpecRunner.html file in a browser to execute them.

To execute specs through jasmine-node, launch:

make test

Performance regression test

There is a small benchmarking HTML page to spot performance regression between currently checked-out quantities.js and any committed version. Just execute:

make bench

then open http://0.0.0.0:3000/bench

Checked-out version is benchmarked against HEAD by default but it could be changed by passing any commit SHA on the command line. Port (default 3000) is also configurable.

make bench COMMIT=e0c7fc468 PORT=5000

TypeScript type declarations

A TypeScript declaration file is published on DefinitelyTyped.

It could be installed with npm install @types/js-quantities.

Contribute

Feedback and contributions are welcomed.

Pull requests must pass tests and linting. Please make sure that make test and make lint return no errors before submitting.

About

JavaScript library for quantity calculation and unit conversion

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

JS-quantities

Build Status

JS-quantities is originally a JavaScript port of Kevin Olbrich's library Ruby Units (http://github.com/olbrich/ruby-units).

The library aims to simplify the handling of units for scientific calculations involving quantities.

JS-quantities is built as UMD and ES modules and can be used with Node.js and browsers. It has no dependencies.

Installation

Install with npm install js-quantities or download latest release v1.7.5 as:

Usage

Node.js

// As CommonJS module
const Qty = require('js-quantities');
// As ES module
import Qty from 'js-quantities/esm';

Browsers

  • UMD module could be included as is:
<scriptsrc='quantities.js'></script>

In this case, it will define a global variable Qty.

define(['quantities'],function(Qty){
...
});

Synopsis

Creation

Instances of quantities are made by means of Qty() method. Qty can both be used as a constructor (with new) or as a factory (without new):

qty=newQty('23 ft');// constructorqty=Qty('23 ft');// factory

Qty constructor accepts strings, numbers and Qty instances as initializing values.

If scalars and their respective units are available programmatically, the two argument signature may be useful:

qty=newQty(124,'cm');// => 1.24 meterqty=Qty(124,'cm');// => 1.24 meter

For the sake of simplicity, one will use the factory way below but using new Qty() is equivalent.

qty=Qty('1m');// => 1 meterqty=Qty('m');// => 1 meter (scalar defaults to 1)qty=Qty('1 N*m');qty=Qty('1 N m');// * is optionalqty=Qty('1 m/s');qty=Qty('1 m^2/s^2');qty=Qty('1 m^2 s^-2');// negative powersqty=Qty('1 m2 s-2');// ^ is optionalqty=Qty('1 m^2 kg^2 J^2/s^2 A');qty=Qty('1.5');// unitless quantityqty=Qty(1.5);// number as initializing valueqty=Qty('1 attoparsec/microfortnight');qtyCopy=Qty(qty);// quantity could be copied when used as// initializing value

Qty.parse utility method is also provided to parse and create quantities from strings. Unlike the constructor, it will return null instead of throwing an error when parsing an invalid quantity.

Qty.parse('1 m');// => 1 meterQty.parse('foo')// => null

Available well-known kinds

Qty.getKinds();// => Array of names of every well-known kind of units

Available units of a particular kind

Qty.getUnits('currency');// => [ 'dollar', 'cents' ]// Or all alphabetically sortedQty.getUnits();// => [ 'acre','Ah','ampere','AMU','angstrom']

Alternative names of a unit

Qty.getAliases('m');// => [ 'm', 'meter', 'meters', 'metre', 'metres' ]

Quantity compatibility, kind and various queries

qty1.isCompatible(qty2);// => true or falseqty.kind();// => 'length', 'area', etc...qty.isUnitless();// => true or falseqty.isBase();// => true if quantity is represented with base units

Conversion

qty.toBase();// converts to SI units (10 cm => 0.1 m) (new instance)qty.toFloat();// returns scalar of unitless quantity// (otherwise throws error)qty.to('m');// converts quantity to meter if compatible// or throws an error (new instance)qty1.to(qty2);// converts quantity to same unit of qty2 if compatible// or throws an error (new instance)qty.inverse();// converts quantity to its inverse// ('100 m/s' => '.01 s/m')// Inverses can be used, but there is no special checking to// rename the unitsQty('10ohm').inverse()// '.1/ohm'// (not '.1S', although they are equivalent)// however, the 'to' command will convert between inverses alsoQty('10ohm').to('S')// '.1S'

Qty.swiftConverter() is a fast way to efficiently convert large array of Number values. It configures a function accepting a value or an array of Number values to convert.

varconvert=Qty.swiftConverter('m/h','ft/s');// Configures converter// Converting single valuevarconverted=convert(2500);// => 2.278..// Converting large array of valuesvarconvertedSerie=convert([2500,5000, ...]);// => [2.278.., 4.556.., ...]

The main drawback of this conversion method is that it does not take care of rounding issues.

Comparison

qty1.eq(qty2);// => true if both quantities are equal (1m == 100cm => true)qty1.same(qty2);// => true if both quantities are same (1m == 100cm => false)qty1.lt(qty2);// => true if qty1 is stricty less than qty2qty1.lte(qty2);// => true if qty1 is less than or equal to qty2qty1.gt(qty2);// => true if qty1 is stricty greater than qty2qty1.gte(qty2);// => true if qty1 is greater than or equal to qty2qty1.compareTo(qty2);// => -1 if qty1 < qty2,// => 0 if qty1 == qty2,// => 1 if qty1 > qty2

Operators

  • add(other): Add. other can be string or quantity. other should be unit compatible.
  • sub(other): Substract. other can be string or quantity. other should be unit compatible.
  • mul(other): Multiply. other can be string, number or quantity.
  • div(other): Divide. other can be string, number or quantity.

Rounding

Qty#toPrec(precision) : returns the nearest multiple of quantity passed as precision.

varqty=Qty('5.17 ft');qty.toPrec('ft');// => 5 ftqty.toPrec('0.5 ft');// => 5 ftqty.toPrec('0.25 ft');// => 5.25 ftqty.toPrec('0.1 ft');// => 5.2 ftqty.toPrec('0.05 ft');// => 5.15 ftqty.toPrec('0.01 ft');// => 5.17 ftqty.toPrec('0.00001 ft');// => 5.17 ftqty.toPrec('2 ft');// => 6 ftqty.toPrec('2');// => 6 ftvarqty=Qty('6.3782 m');qty.toPrec('dm');// => 6.4 mqty.toPrec('cm');// => 6.38 mqty.toPrec('mm');// => 6.378 mqty.toPrec('5 cm');// => 6.4 mqty.toPrec('10 m');// => 10 mqty.toPrec(0.1);// => 6.3 mvarqty=Qty('1.146 MPa');qty.toPrec('0.1 bar');// => 1.15 MPa

Formatting quantities

Qty#toString returns a string using the canonical form of the quantity (that is it could be seamlessly reparsed by Qty).

varqty=Qty('1.146 MPa');qty.toString();// => '1.146 MPa'

As a shorthand, units could be passed to Qty#toString and is equivalent to successively call Qty#to then Qty#toString.

varqty=Qty('1.146 MPa');qty.toString('bar');// => '11.46 bar'qty.to('bar').toString();// => '11.46 bar'

Qty#toString could also be used with any method from Qty to make some sort of formatting. For instance, one could use Qty#toPrec to fix the maximum number of decimals:

varqty=Qty('1.146 MPa');qty.toPrec(0.1).toString();// => '1.1 MPa'qty.to('bar').toPrec(0.1).toString();// => '11.5 bar'

For advanced formatting needs as localization, specific rounding or any other custom customization, quantities can be transformed into strings through Qty#format according to optional target units and formatter. If target units are specified, the quantity is converted into them before formatting.

Such a string is not intended to be reparsed to construct a new instance of Qty (unlike output of Qty#toString).

If no formatter is specified, quantities are formatted according to default js-quantities' formatter and is equivalent to Qty#toString.

varqty=Qty('1.1234 m');qty.format();// same units, default formatter => '1.234 m'qty.format('cm');// converted to 'cm', default formatter => '123.45 cm'

Qty#format could delegates formatting to a custom formatter if required. A formatter is a callback function accepting scalar and units as parameters and returning a formatted string representing the quantity.

varconfigurableRoundingFormatter=function(maxDecimals){returnfunction(scalar,units){varpow=Math.pow(10,maxDecimals);varrounded=Math.round(scalar*pow)/pow;returnrounded+' '+units;};};varqty=Qty('1.1234 m');// same units, custom formatter => '1.12 m'qty.format(configurableRoundingFormatter(2));// convert to 'cm', custom formatter => '123.4 cm'qty.format('cm',configurableRoundingFormatter(1));

Custom formatter can be configured globally by setting Qty.formatter.

Qty.formatter=configurableRoundingFormatter(2);varqty=Qty('1.1234 m');qty.format();// same units, current default formatter => '1.12 m'

Temperatures

Like ruby-units, JS-quantities makes a distinction between a temperature (which technically is a property) and degrees of temperature (which temperatures are measured in).

Temperature units (i.e., 'tempK') can be converted back and forth, and will take into account the differences in the zero points of the various scales. Differential temperature (e.g., '100 degC') units behave like most other units.

Qty('37 tempC').to('tempF')// => 98.6 tempF

JS-quantities will throw an error if you attempt to create a temperature unit that would fall below absolute zero.

Unit math on temperatures is fairly limited.

Qty('100 tempC').add('10 degC')// 110 tempCQty('100 tempC').sub('10 degC')// 90 tempCQty('100 tempC').add('50 tempC')// throws errorQty('100 tempC').sub('50 tempC')// 50 degCQty('50 tempC').sub('100 tempC')// -50 degCQty('100 tempC').mul(scalar)// 100*scalar tempCQty('100 tempC').div(scalar)// 100/scalar tempCQty('100 tempC').mul(qty)// throws errorQty('100 tempC').div(qty)// throws errorQty('100 tempC*unit')// throws errorQty('100 tempC/unit')// throws errorQty('100 unit/tempC')// throws errorQty('100 tempC').inverse()// throws error
Qty('100 tempC').to('degC')// => 100 degC

This conversion references the 0 point on the scale of the temperature unit

Qty('100 degC').to('tempC')// => -173.15 tempC

These conversions are always interpreted as being relative to absolute zero. Conversions are probably better done like this...

Qty('0 tempC').add('100 degC')// => 100 tempC

Errors

Every error thrown by JS-quantities is an instance of Qty.Error.

try{// code triggering an error inside JS-quantities}catch(e){if(einstanceofQty.Error){// ...}else{// ...}}

Tests

Tests are implemented with Jasmine (https://github.com/pivotal/jasmine). You could use both HTML and jasmine-node runners.

To execute specs through HTML runner, just open SpecRunner.html file in a browser to execute them.

To execute specs through jasmine-node, launch:

make test

Performance regression test

There is a small benchmarking HTML page to spot performance regression between currently checked-out quantities.js and any committed version. Just execute:

make bench

then open http://0.0.0.0:3000/bench

Checked-out version is benchmarked against HEAD by default but it could be changed by passing any commit SHA on the command line. Port (default 3000) is also configurable.

make bench COMMIT=e0c7fc468 PORT=5000

TypeScript type declarations

A TypeScript declaration file is published on DefinitelyTyped.

It could be installed with npm install @types/js-quantities.

Contribute

Feedback and contributions are welcomed.

Pull requests must pass tests and linting. Please make sure that make test and make lint return no errors before submitting.

About

JavaScript library for quantity calculation and unit conversion

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

JS-quantities

Build Status

JS-quantities is originally a JavaScript port of Kevin Olbrich's library Ruby Units (http://github.com/olbrich/ruby-units).

The library aims to simplify the handling of units for scientific calculations involving quantities.

JS-quantities is built as UMD and ES modules and can be used with Node.js and browsers. It has no dependencies.

Installation

Install with npm install js-quantities or download latest release v1.7.5 as:

Usage

Node.js

// As CommonJS module
const Qty = require('js-quantities');
// As ES module
import Qty from 'js-quantities/esm';

Browsers

  • UMD module could be included as is:
<scriptsrc='quantities.js'></script>

In this case, it will define a global variable Qty.

define(['quantities'],function(Qty){
...
});

Synopsis

Creation

Instances of quantities are made by means of Qty() method. Qty can both be used as a constructor (with new) or as a factory (without new):

qty=newQty('23 ft');// constructorqty=Qty('23 ft');// factory

Qty constructor accepts strings, numbers and Qty instances as initializing values.

If scalars and their respective units are available programmatically, the two argument signature may be useful:

qty=newQty(124,'cm');// => 1.24 meterqty=Qty(124,'cm');// => 1.24 meter

For the sake of simplicity, one will use the factory way below but using new Qty() is equivalent.

qty=Qty('1m');// => 1 meterqty=Qty('m');// => 1 meter (scalar defaults to 1)qty=Qty('1 N*m');qty=Qty('1 N m');// * is optionalqty=Qty('1 m/s');qty=Qty('1 m^2/s^2');qty=Qty('1 m^2 s^-2');// negative powersqty=Qty('1 m2 s-2');// ^ is optionalqty=Qty('1 m^2 kg^2 J^2/s^2 A');qty=Qty('1.5');// unitless quantityqty=Qty(1.5);// number as initializing valueqty=Qty('1 attoparsec/microfortnight');qtyCopy=Qty(qty);// quantity could be copied when used as// initializing value

Qty.parse utility method is also provided to parse and create quantities from strings. Unlike the constructor, it will return null instead of throwing an error when parsing an invalid quantity.

Qty.parse('1 m');// => 1 meterQty.parse('foo')// => null

Available well-known kinds

Qty.getKinds();// => Array of names of every well-known kind of units

Available units of a particular kind

Qty.getUnits('currency');// => [ 'dollar', 'cents' ]// Or all alphabetically sortedQty.getUnits();// => [ 'acre','Ah','ampere','AMU','angstrom']

Alternative names of a unit

Qty.getAliases('m');// => [ 'm', 'meter', 'meters', 'metre', 'metres' ]

Quantity compatibility, kind and various queries

qty1.isCompatible(qty2);// => true or falseqty.kind();// => 'length', 'area', etc...qty.isUnitless();// => true or falseqty.isBase();// => true if quantity is represented with base units

Conversion

qty.toBase();// converts to SI units (10 cm => 0.1 m) (new instance)qty.toFloat();// returns scalar of unitless quantity// (otherwise throws error)qty.to('m');// converts quantity to meter if compatible// or throws an error (new instance)qty1.to(qty2);// converts quantity to same unit of qty2 if compatible// or throws an error (new instance)qty.inverse();// converts quantity to its inverse// ('100 m/s' => '.01 s/m')// Inverses can be used, but there is no special checking to// rename the unitsQty('10ohm').inverse()// '.1/ohm'// (not '.1S', although they are equivalent)// however, the 'to' command will convert between inverses alsoQty('10ohm').to('S')// '.1S'

Qty.swiftConverter() is a fast way to efficiently convert large array of Number values. It configures a function accepting a value or an array of Number values to convert.

varconvert=Qty.swiftConverter('m/h','ft/s');// Configures converter// Converting single valuevarconverted=convert(2500);// => 2.278..// Converting large array of valuesvarconvertedSerie=convert([2500,5000, ...]);// => [2.278.., 4.556.., ...]

The main drawback of this conversion method is that it does not take care of rounding issues.

Comparison

qty1.eq(qty2);// => true if both quantities are equal (1m == 100cm => true)qty1.same(qty2);// => true if both quantities are same (1m == 100cm => false)qty1.lt(qty2);// => true if qty1 is stricty less than qty2qty1.lte(qty2);// => true if qty1 is less than or equal to qty2qty1.gt(qty2);// => true if qty1 is stricty greater than qty2qty1.gte(qty2);// => true if qty1 is greater than or equal to qty2qty1.compareTo(qty2);// => -1 if qty1 < qty2,// => 0 if qty1 == qty2,// => 1 if qty1 > qty2

Operators

  • add(other): Add. other can be string or quantity. other should be unit compatible.
  • sub(other): Substract. other can be string or quantity. other should be unit compatible.
  • mul(other): Multiply. other can be string, number or quantity.
  • div(other): Divide. other can be string, number or quantity.

Rounding

Qty#toPrec(precision) : returns the nearest multiple of quantity passed as precision.

varqty=Qty('5.17 ft');qty.toPrec('ft');// => 5 ftqty.toPrec('0.5 ft');// => 5 ftqty.toPrec('0.25 ft');// => 5.25 ftqty.toPrec('0.1 ft');// => 5.2 ftqty.toPrec('0.05 ft');// => 5.15 ftqty.toPrec('0.01 ft');// => 5.17 ftqty.toPrec('0.00001 ft');// => 5.17 ftqty.toPrec('2 ft');// => 6 ftqty.toPrec('2');// => 6 ftvarqty=Qty('6.3782 m');qty.toPrec('dm');// => 6.4 mqty.toPrec('cm');// => 6.38 mqty.toPrec('mm');// => 6.378 mqty.toPrec('5 cm');// => 6.4 mqty.toPrec('10 m');// => 10 mqty.toPrec(0.1);// => 6.3 mvarqty=Qty('1.146 MPa');qty.toPrec('0.1 bar');// => 1.15 MPa

Formatting quantities

Qty#toString returns a string using the canonical form of the quantity (that is it could be seamlessly reparsed by Qty).

varqty=Qty('1.146 MPa');qty.toString();// => '1.146 MPa'

As a shorthand, units could be passed to Qty#toString and is equivalent to successively call Qty#to then Qty#toString.

varqty=Qty('1.146 MPa');qty.toString('bar');// => '11.46 bar'qty.to('bar').toString();// => '11.46 bar'

Qty#toString could also be used with any method from Qty to make some sort of formatting. For instance, one could use Qty#toPrec to fix the maximum number of decimals:

varqty=Qty('1.146 MPa');qty.toPrec(0.1).toString();// => '1.1 MPa'qty.to('bar').toPrec(0.1).toString();// => '11.5 bar'

For advanced formatting needs as localization, specific rounding or any other custom customization, quantities can be transformed into strings through Qty#format according to optional target units and formatter. If target units are specified, the quantity is converted into them before formatting.

Such a string is not intended to be reparsed to construct a new instance of Qty (unlike output of Qty#toString).

If no formatter is specified, quantities are formatted according to default js-quantities' formatter and is equivalent to Qty#toString.

varqty=Qty('1.1234 m');qty.format();// same units, default formatter => '1.234 m'qty.format('cm');// converted to 'cm', default formatter => '123.45 cm'

Qty#format could delegates formatting to a custom formatter if required. A formatter is a callback function accepting scalar and units as parameters and returning a formatted string representing the quantity.

varconfigurableRoundingFormatter=function(maxDecimals){returnfunction(scalar,units){varpow=Math.pow(10,maxDecimals);varrounded=Math.round(scalar*pow)/pow;returnrounded+' '+units;};};varqty=Qty('1.1234 m');// same units, custom formatter => '1.12 m'qty.format(configurableRoundingFormatter(2));// convert to 'cm', custom formatter => '123.4 cm'qty.format('cm',configurableRoundingFormatter(1));

Custom formatter can be configured globally by setting Qty.formatter.

Qty.formatter=configurableRoundingFormatter(2);varqty=Qty('1.1234 m');qty.format();// same units, current default formatter => '1.12 m'

Temperatures

Like ruby-units, JS-quantities makes a distinction between a temperature (which technically is a property) and degrees of temperature (which temperatures are measured in).

Temperature units (i.e., 'tempK') can be converted back and forth, and will take into account the differences in the zero points of the various scales. Differential temperature (e.g., '100 degC') units behave like most other units.

Qty('37 tempC').to('tempF')// => 98.6 tempF

JS-quantities will throw an error if you attempt to create a temperature unit that would fall below absolute zero.

Unit math on temperatures is fairly limited.

Qty('100 tempC').add('10 degC')// 110 tempCQty('100 tempC').sub('10 degC')// 90 tempCQty('100 tempC').add('50 tempC')// throws errorQty('100 tempC').sub('50 tempC')// 50 degCQty('50 tempC').sub('100 tempC')// -50 degCQty('100 tempC').mul(scalar)// 100*scalar tempCQty('100 tempC').div(scalar)// 100/scalar tempCQty('100 tempC').mul(qty)// throws errorQty('100 tempC').div(qty)// throws errorQty('100 tempC*unit')// throws errorQty('100 tempC/unit')// throws errorQty('100 unit/tempC')// throws errorQty('100 tempC').inverse()// throws error
Qty('100 tempC').to('degC')// => 100 degC

This conversion references the 0 point on the scale of the temperature unit

Qty('100 degC').to('tempC')// => -173.15 tempC

These conversions are always interpreted as being relative to absolute zero. Conversions are probably better done like this...

Qty('0 tempC').add('100 degC')// => 100 tempC

Errors

Every error thrown by JS-quantities is an instance of Qty.Error.

try{// code triggering an error inside JS-quantities}catch(e){if(einstanceofQty.Error){// ...}else{// ...}}

Tests

Tests are implemented with Jasmine (https://github.com/pivotal/jasmine). You could use both HTML and jasmine-node runners.

To execute specs through HTML runner, just open SpecRunner.html file in a browser to execute them.

To execute specs through jasmine-node, launch:

make test

Performance regression test

There is a small benchmarking HTML page to spot performance regression between currently checked-out quantities.js and any committed version. Just execute:

make bench

then open http://0.0.0.0:3000/bench

Checked-out version is benchmarked against HEAD by default but it could be changed by passing any commit SHA on the command line. Port (default 3000) is also configurable.

make bench COMMIT=e0c7fc468 PORT=5000

TypeScript type declarations

A TypeScript declaration file is published on DefinitelyTyped.

It could be installed with npm install @types/js-quantities.

Contribute

Feedback and contributions are welcomed.

Pull requests must pass tests and linting. Please make sure that make test and make lint return no errors before submitting.

About

JavaScript library for quantity calculation and unit conversion

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

JS-quantities

Build Status

JS-quantities is originally a JavaScript port of Kevin Olbrich's library Ruby Units (http://github.com/olbrich/ruby-units).

The library aims to simplify the handling of units for scientific calculations involving quantities.

JS-quantities is built as UMD and ES modules and can be used with Node.js and browsers. It has no dependencies.

Installation

Install with npm install js-quantities or download latest release v1.7.5 as:

Usage

Node.js

// As CommonJS module
const Qty = require('js-quantities');
// As ES module
import Qty from 'js-quantities/esm';

Browsers

  • UMD module could be included as is:
<scriptsrc='quantities.js'></script>

In this case, it will define a global variable Qty.

define(['quantities'],function(Qty){
...
});

Synopsis

Creation

Instances of quantities are made by means of Qty() method. Qty can both be used as a constructor (with new) or as a factory (without new):

qty=newQty('23 ft');// constructorqty=Qty('23 ft');// factory

Qty constructor accepts strings, numbers and Qty instances as initializing values.

If scalars and their respective units are available programmatically, the two argument signature may be useful:

qty=newQty(124,'cm');// => 1.24 meterqty=Qty(124,'cm');// => 1.24 meter

For the sake of simplicity, one will use the factory way below but using new Qty() is equivalent.

qty=Qty('1m');// => 1 meterqty=Qty('m');// => 1 meter (scalar defaults to 1)qty=Qty('1 N*m');qty=Qty('1 N m');// * is optionalqty=Qty('1 m/s');qty=Qty('1 m^2/s^2');qty=Qty('1 m^2 s^-2');// negative powersqty=Qty('1 m2 s-2');// ^ is optionalqty=Qty('1 m^2 kg^2 J^2/s^2 A');qty=Qty('1.5');// unitless quantityqty=Qty(1.5);// number as initializing valueqty=Qty('1 attoparsec/microfortnight');qtyCopy=Qty(qty);// quantity could be copied when used as// initializing value

Qty.parse utility method is also provided to parse and create quantities from strings. Unlike the constructor, it will return null instead of throwing an error when parsing an invalid quantity.

Qty.parse('1 m');// => 1 meterQty.parse('foo')// => null

Available well-known kinds

Qty.getKinds();// => Array of names of every well-known kind of units

Available units of a particular kind

Qty.getUnits('currency');// => [ 'dollar', 'cents' ]// Or all alphabetically sortedQty.getUnits();// => [ 'acre','Ah','ampere','AMU','angstrom']

Alternative names of a unit

Qty.getAliases('m');// => [ 'm', 'meter', 'meters', 'metre', 'metres' ]

Quantity compatibility, kind and various queries

qty1.isCompatible(qty2);// => true or falseqty.kind();// => 'length', 'area', etc...qty.isUnitless();// => true or falseqty.isBase();// => true if quantity is represented with base units

Conversion

qty.toBase();// converts to SI units (10 cm => 0.1 m) (new instance)qty.toFloat();// returns scalar of unitless quantity// (otherwise throws error)qty.to('m');// converts quantity to meter if compatible// or throws an error (new instance)qty1.to(qty2);// converts quantity to same unit of qty2 if compatible// or throws an error (new instance)qty.inverse();// converts quantity to its inverse// ('100 m/s' => '.01 s/m')// Inverses can be used, but there is no special checking to// rename the unitsQty('10ohm').inverse()// '.1/ohm'// (not '.1S', although they are equivalent)// however, the 'to' command will convert between inverses alsoQty('10ohm').to('S')// '.1S'

Qty.swiftConverter() is a fast way to efficiently convert large array of Number values. It configures a function accepting a value or an array of Number values to convert.

varconvert=Qty.swiftConverter('m/h','ft/s');// Configures converter// Converting single valuevarconverted=convert(2500);// => 2.278..// Converting large array of valuesvarconvertedSerie=convert([2500,5000, ...]);// => [2.278.., 4.556.., ...]

The main drawback of this conversion method is that it does not take care of rounding issues.

Comparison

qty1.eq(qty2);// => true if both quantities are equal (1m == 100cm => true)qty1.same(qty2);// => true if both quantities are same (1m == 100cm => false)qty1.lt(qty2);// => true if qty1 is stricty less than qty2qty1.lte(qty2);// => true if qty1 is less than or equal to qty2qty1.gt(qty2);// => true if qty1 is stricty greater than qty2qty1.gte(qty2);// => true if qty1 is greater than or equal to qty2qty1.compareTo(qty2);// => -1 if qty1 < qty2,// => 0 if qty1 == qty2,// => 1 if qty1 > qty2

Operators

  • add(other): Add. other can be string or quantity. other should be unit compatible.
  • sub(other): Substract. other can be string or quantity. other should be unit compatible.
  • mul(other): Multiply. other can be string, number or quantity.
  • div(other): Divide. other can be string, number or quantity.

Rounding

Qty#toPrec(precision) : returns the nearest multiple of quantity passed as precision.

varqty=Qty('5.17 ft');qty.toPrec('ft');// => 5 ftqty.toPrec('0.5 ft');// => 5 ftqty.toPrec('0.25 ft');// => 5.25 ftqty.toPrec('0.1 ft');// => 5.2 ftqty.toPrec('0.05 ft');// => 5.15 ftqty.toPrec('0.01 ft');// => 5.17 ftqty.toPrec('0.00001 ft');// => 5.17 ftqty.toPrec('2 ft');// => 6 ftqty.toPrec('2');// => 6 ftvarqty=Qty('6.3782 m');qty.toPrec('dm');// => 6.4 mqty.toPrec('cm');// => 6.38 mqty.toPrec('mm');// => 6.378 mqty.toPrec('5 cm');// => 6.4 mqty.toPrec('10 m');// => 10 mqty.toPrec(0.1);// => 6.3 mvarqty=Qty('1.146 MPa');qty.toPrec('0.1 bar');// => 1.15 MPa

Formatting quantities

Qty#toString returns a string using the canonical form of the quantity (that is it could be seamlessly reparsed by Qty).

varqty=Qty('1.146 MPa');qty.toString();// => '1.146 MPa'

As a shorthand, units could be passed to Qty#toString and is equivalent to successively call Qty#to then Qty#toString.

varqty=Qty('1.146 MPa');qty.toString('bar');// => '11.46 bar'qty.to('bar').toString();// => '11.46 bar'

Qty#toString could also be used with any method from Qty to make some sort of formatting. For instance, one could use Qty#toPrec to fix the maximum number of decimals:

varqty=Qty('1.146 MPa');qty.toPrec(0.1).toString();// => '1.1 MPa'qty.to('bar').toPrec(0.1).toString();// => '11.5 bar'

For advanced formatting needs as localization, specific rounding or any other custom customization, quantities can be transformed into strings through Qty#format according to optional target units and formatter. If target units are specified, the quantity is converted into them before formatting.

Such a string is not intended to be reparsed to construct a new instance of Qty (unlike output of Qty#toString).

If no formatter is specified, quantities are formatted according to default js-quantities' formatter and is equivalent to Qty#toString.

varqty=Qty('1.1234 m');qty.format();// same units, default formatter => '1.234 m'qty.format('cm');// converted to 'cm', default formatter => '123.45 cm'

Qty#format could delegates formatting to a custom formatter if required. A formatter is a callback function accepting scalar and units as parameters and returning a formatted string representing the quantity.

varconfigurableRoundingFormatter=function(maxDecimals){returnfunction(scalar,units){varpow=Math.pow(10,maxDecimals);varrounded=Math.round(scalar*pow)/pow;returnrounded+' '+units;};};varqty=Qty('1.1234 m');// same units, custom formatter => '1.12 m'qty.format(configurableRoundingFormatter(2));// convert to 'cm', custom formatter => '123.4 cm'qty.format('cm',configurableRoundingFormatter(1));

Custom formatter can be configured globally by setting Qty.formatter.

Qty.formatter=configurableRoundingFormatter(2);varqty=Qty('1.1234 m');qty.format();// same units, current default formatter => '1.12 m'

Temperatures

Like ruby-units, JS-quantities makes a distinction between a temperature (which technically is a property) and degrees of temperature (which temperatures are measured in).

Temperature units (i.e., 'tempK') can be converted back and forth, and will take into account the differences in the zero points of the various scales. Differential temperature (e.g., '100 degC') units behave like most other units.

Qty('37 tempC').to('tempF')// => 98.6 tempF

JS-quantities will throw an error if you attempt to create a temperature unit that would fall below absolute zero.

Unit math on temperatures is fairly limited.

Qty('100 tempC').add('10 degC')// 110 tempCQty('100 tempC').sub('10 degC')// 90 tempCQty('100 tempC').add('50 tempC')// throws errorQty('100 tempC').sub('50 tempC')// 50 degCQty('50 tempC').sub('100 tempC')// -50 degCQty('100 tempC').mul(scalar)// 100*scalar tempCQty('100 tempC').div(scalar)// 100/scalar tempCQty('100 tempC').mul(qty)// throws errorQty('100 tempC').div(qty)// throws errorQty('100 tempC*unit')// throws errorQty('100 tempC/unit')// throws errorQty('100 unit/tempC')// throws errorQty('100 tempC').inverse()// throws error
Qty('100 tempC').to('degC')// => 100 degC

This conversion references the 0 point on the scale of the temperature unit

Qty('100 degC').to('tempC')// => -173.15 tempC

These conversions are always interpreted as being relative to absolute zero. Conversions are probably better done like this...

Qty('0 tempC').add('100 degC')// => 100 tempC

Errors

Every error thrown by JS-quantities is an instance of Qty.Error.

try{// code triggering an error inside JS-quantities}catch(e){if(einstanceofQty.Error){// ...}else{// ...}}

Tests

Tests are implemented with Jasmine (https://github.com/pivotal/jasmine). You could use both HTML and jasmine-node runners.

To execute specs through HTML runner, just open SpecRunner.html file in a browser to execute them.

To execute specs through jasmine-node, launch:

make test

Performance regression test

There is a small benchmarking HTML page to spot performance regression between currently checked-out quantities.js and any committed version. Just execute:

make bench

then open http://0.0.0.0:3000/bench

Checked-out version is benchmarked against HEAD by default but it could be changed by passing any commit SHA on the command line. Port (default 3000) is also configurable.

make bench COMMIT=e0c7fc468 PORT=5000

TypeScript type declarations

A TypeScript declaration file is published on DefinitelyTyped.

It could be installed with npm install @types/js-quantities.

Contribute

Feedback and contributions are welcomed.

Pull requests must pass tests and linting. Please make sure that make test and make lint return no errors before submitting.

About

JavaScript library for quantity calculation and unit conversion

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

JS-quantities

Build Status

JS-quantities is originally a JavaScript port of Kevin Olbrich's library Ruby Units (http://github.com/olbrich/ruby-units).

The library aims to simplify the handling of units for scientific calculations involving quantities.

JS-quantities is built as UMD and ES modules and can be used with Node.js and browsers. It has no dependencies.

Installation

Install with npm install js-quantities or download latest release v1.7.5 as:

Usage

Node.js

// As CommonJS module
const Qty = require('js-quantities');
// As ES module
import Qty from 'js-quantities/esm';

Browsers

  • UMD module could be included as is:
<scriptsrc='quantities.js'></script>

In this case, it will define a global variable Qty.

define(['quantities'],function(Qty){
...
});

Synopsis

Creation

Instances of quantities are made by means of Qty() method. Qty can both be used as a constructor (with new) or as a factory (without new):

qty=newQty('23 ft');// constructorqty=Qty('23 ft');// factory

Qty constructor accepts strings, numbers and Qty instances as initializing values.

If scalars and their respective units are available programmatically, the two argument signature may be useful:

qty=newQty(124,'cm');// => 1.24 meterqty=Qty(124,'cm');// => 1.24 meter

For the sake of simplicity, one will use the factory way below but using new Qty() is equivalent.

qty=Qty('1m');// => 1 meterqty=Qty('m');// => 1 meter (scalar defaults to 1)qty=Qty('1 N*m');qty=Qty('1 N m');// * is optionalqty=Qty('1 m/s');qty=Qty('1 m^2/s^2');qty=Qty('1 m^2 s^-2');// negative powersqty=Qty('1 m2 s-2');// ^ is optionalqty=Qty('1 m^2 kg^2 J^2/s^2 A');qty=Qty('1.5');// unitless quantityqty=Qty(1.5);// number as initializing valueqty=Qty('1 attoparsec/microfortnight');qtyCopy=Qty(qty);// quantity could be copied when used as// initializing value

Qty.parse utility method is also provided to parse and create quantities from strings. Unlike the constructor, it will return null instead of throwing an error when parsing an invalid quantity.

Qty.parse('1 m');// => 1 meterQty.parse('foo')// => null

Available well-known kinds

Qty.getKinds();// => Array of names of every well-known kind of units

Available units of a particular kind

Qty.getUnits('currency');// => [ 'dollar', 'cents' ]// Or all alphabetically sortedQty.getUnits();// => [ 'acre','Ah','ampere','AMU','angstrom']

Alternative names of a unit

Qty.getAliases('m');// => [ 'm', 'meter', 'meters', 'metre', 'metres' ]

Quantity compatibility, kind and various queries

qty1.isCompatible(qty2);// => true or falseqty.kind();// => 'length', 'area', etc...qty.isUnitless();// => true or falseqty.isBase();// => true if quantity is represented with base units

Conversion

qty.toBase();// converts to SI units (10 cm => 0.1 m) (new instance)qty.toFloat();// returns scalar of unitless quantity// (otherwise throws error)qty.to('m');// converts quantity to meter if compatible// or throws an error (new instance)qty1.to(qty2);// converts quantity to same unit of qty2 if compatible// or throws an error (new instance)qty.inverse();// converts quantity to its inverse// ('100 m/s' => '.01 s/m')// Inverses can be used, but there is no special checking to// rename the unitsQty('10ohm').inverse()// '.1/ohm'// (not '.1S', although they are equivalent)// however, the 'to' command will convert between inverses alsoQty('10ohm').to('S')// '.1S'

Qty.swiftConverter() is a fast way to efficiently convert large array of Number values. It configures a function accepting a value or an array of Number values to convert.

varconvert=Qty.swiftConverter('m/h','ft/s');// Configures converter// Converting single valuevarconverted=convert(2500);// => 2.278..// Converting large array of valuesvarconvertedSerie=convert([2500,5000, ...]);// => [2.278.., 4.556.., ...]

The main drawback of this conversion method is that it does not take care of rounding issues.

Comparison

qty1.eq(qty2);// => true if both quantities are equal (1m == 100cm => true)qty1.same(qty2);// => true if both quantities are same (1m == 100cm => false)qty1.lt(qty2);// => true if qty1 is stricty less than qty2qty1.lte(qty2);// => true if qty1 is less than or equal to qty2qty1.gt(qty2);// => true if qty1 is stricty greater than qty2qty1.gte(qty2);// => true if qty1 is greater than or equal to qty2qty1.compareTo(qty2);// => -1 if qty1 < qty2,// => 0 if qty1 == qty2,// => 1 if qty1 > qty2

Operators

  • add(other): Add. other can be string or quantity. other should be unit compatible.
  • sub(other): Substract. other can be string or quantity. other should be unit compatible.
  • mul(other): Multiply. other can be string, number or quantity.
  • div(other): Divide. other can be string, number or quantity.

Rounding

Qty#toPrec(precision) : returns the nearest multiple of quantity passed as precision.

varqty=Qty('5.17 ft');qty.toPrec('ft');// => 5 ftqty.toPrec('0.5 ft');// => 5 ftqty.toPrec('0.25 ft');// => 5.25 ftqty.toPrec('0.1 ft');// => 5.2 ftqty.toPrec('0.05 ft');// => 5.15 ftqty.toPrec('0.01 ft');// => 5.17 ftqty.toPrec('0.00001 ft');// => 5.17 ftqty.toPrec('2 ft');// => 6 ftqty.toPrec('2');// => 6 ftvarqty=Qty('6.3782 m');qty.toPrec('dm');// => 6.4 mqty.toPrec('cm');// => 6.38 mqty.toPrec('mm');// => 6.378 mqty.toPrec('5 cm');// => 6.4 mqty.toPrec('10 m');// => 10 mqty.toPrec(0.1);// => 6.3 mvarqty=Qty('1.146 MPa');qty.toPrec('0.1 bar');// => 1.15 MPa

Formatting quantities

Qty#toString returns a string using the canonical form of the quantity (that is it could be seamlessly reparsed by Qty).

varqty=Qty('1.146 MPa');qty.toString();// => '1.146 MPa'

As a shorthand, units could be passed to Qty#toString and is equivalent to successively call Qty#to then Qty#toString.

varqty=Qty('1.146 MPa');qty.toString('bar');// => '11.46 bar'qty.to('bar').toString();// => '11.46 bar'

Qty#toString could also be used with any method from Qty to make some sort of formatting. For instance, one could use Qty#toPrec to fix the maximum number of decimals:

varqty=Qty('1.146 MPa');qty.toPrec(0.1).toString();// => '1.1 MPa'qty.to('bar').toPrec(0.1).toString();// => '11.5 bar'

For advanced formatting needs as localization, specific rounding or any other custom customization, quantities can be transformed into strings through Qty#format according to optional target units and formatter. If target units are specified, the quantity is converted into them before formatting.

Such a string is not intended to be reparsed to construct a new instance of Qty (unlike output of Qty#toString).

If no formatter is specified, quantities are formatted according to default js-quantities' formatter and is equivalent to Qty#toString.

varqty=Qty('1.1234 m');qty.format();// same units, default formatter => '1.234 m'qty.format('cm');// converted to 'cm', default formatter => '123.45 cm'

Qty#format could delegates formatting to a custom formatter if required. A formatter is a callback function accepting scalar and units as parameters and returning a formatted string representing the quantity.

varconfigurableRoundingFormatter=function(maxDecimals){returnfunction(scalar,units){varpow=Math.pow(10,maxDecimals);varrounded=Math.round(scalar*pow)/pow;returnrounded+' '+units;};};varqty=Qty('1.1234 m');// same units, custom formatter => '1.12 m'qty.format(configurableRoundingFormatter(2));// convert to 'cm', custom formatter => '123.4 cm'qty.format('cm',configurableRoundingFormatter(1));

Custom formatter can be configured globally by setting Qty.formatter.

Qty.formatter=configurableRoundingFormatter(2);varqty=Qty('1.1234 m');qty.format();// same units, current default formatter => '1.12 m'

Temperatures

Like ruby-units, JS-quantities makes a distinction between a temperature (which technically is a property) and degrees of temperature (which temperatures are measured in).

Temperature units (i.e., 'tempK') can be converted back and forth, and will take into account the differences in the zero points of the various scales. Differential temperature (e.g., '100 degC') units behave like most other units.

Qty('37 tempC').to('tempF')// => 98.6 tempF

JS-quantities will throw an error if you attempt to create a temperature unit that would fall below absolute zero.

Unit math on temperatures is fairly limited.

Qty('100 tempC').add('10 degC')// 110 tempCQty('100 tempC').sub('10 degC')// 90 tempCQty('100 tempC').add('50 tempC')// throws errorQty('100 tempC').sub('50 tempC')// 50 degCQty('50 tempC').sub('100 tempC')// -50 degCQty('100 tempC').mul(scalar)// 100*scalar tempCQty('100 tempC').div(scalar)// 100/scalar tempCQty('100 tempC').mul(qty)// throws errorQty('100 tempC').div(qty)// throws errorQty('100 tempC*unit')// throws errorQty('100 tempC/unit')// throws errorQty('100 unit/tempC')// throws errorQty('100 tempC').inverse()// throws error
Qty('100 tempC').to('degC')// => 100 degC

This conversion references the 0 point on the scale of the temperature unit

Qty('100 degC').to('tempC')// => -173.15 tempC

These conversions are always interpreted as being relative to absolute zero. Conversions are probably better done like this...

Qty('0 tempC').add('100 degC')// => 100 tempC

Errors

Every error thrown by JS-quantities is an instance of Qty.Error.

try{// code triggering an error inside JS-quantities}catch(e){if(einstanceofQty.Error){// ...}else{// ...}}

Tests

Tests are implemented with Jasmine (https://github.com/pivotal/jasmine). You could use both HTML and jasmine-node runners.

To execute specs through HTML runner, just open SpecRunner.html file in a browser to execute them.

To execute specs through jasmine-node, launch:

make test

Performance regression test

There is a small benchmarking HTML page to spot performance regression between currently checked-out quantities.js and any committed version. Just execute:

make bench

then open http://0.0.0.0:3000/bench

Checked-out version is benchmarked against HEAD by default but it could be changed by passing any commit SHA on the command line. Port (default 3000) is also configurable.

make bench COMMIT=e0c7fc468 PORT=5000

TypeScript type declarations

A TypeScript declaration file is published on DefinitelyTyped.

It could be installed with npm install @types/js-quantities.

Contribute

Feedback and contributions are welcomed.

Pull requests must pass tests and linting. Please make sure that make test and make lint return no errors before submitting.

About

JavaScript library for quantity calculation and unit conversion

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

JS-quantities

Build Status

JS-quantities is originally a JavaScript port of Kevin Olbrich's library Ruby Units (http://github.com/olbrich/ruby-units).

The library aims to simplify the handling of units for scientific calculations involving quantities.

JS-quantities is built as UMD and ES modules and can be used with Node.js and browsers. It has no dependencies.

Installation

Install with npm install js-quantities or download latest release v1.7.5 as:

Usage

Node.js

// As CommonJS module
const Qty = require('js-quantities');
// As ES module
import Qty from 'js-quantities/esm';

Browsers

  • UMD module could be included as is:
<scriptsrc='quantities.js'></script>

In this case, it will define a global variable Qty.

define(['quantities'],function(Qty){
...
});

Synopsis

Creation

Instances of quantities are made by means of Qty() method. Qty can both be used as a constructor (with new) or as a factory (without new):

qty=newQty('23 ft');// constructorqty=Qty('23 ft');// factory

Qty constructor accepts strings, numbers and Qty instances as initializing values.

If scalars and their respective units are available programmatically, the two argument signature may be useful:

qty=newQty(124,'cm');// => 1.24 meterqty=Qty(124,'cm');// => 1.24 meter

For the sake of simplicity, one will use the factory way below but using new Qty() is equivalent.

qty=Qty('1m');// => 1 meterqty=Qty('m');// => 1 meter (scalar defaults to 1)qty=Qty('1 N*m');qty=Qty('1 N m');// * is optionalqty=Qty('1 m/s');qty=Qty('1 m^2/s^2');qty=Qty('1 m^2 s^-2');// negative powersqty=Qty('1 m2 s-2');// ^ is optionalqty=Qty('1 m^2 kg^2 J^2/s^2 A');qty=Qty('1.5');// unitless quantityqty=Qty(1.5);// number as initializing valueqty=Qty('1 attoparsec/microfortnight');qtyCopy=Qty(qty);// quantity could be copied when used as// initializing value

Qty.parse utility method is also provided to parse and create quantities from strings. Unlike the constructor, it will return null instead of throwing an error when parsing an invalid quantity.

Qty.parse('1 m');// => 1 meterQty.parse('foo')// => null

Available well-known kinds

Qty.getKinds();// => Array of names of every well-known kind of units

Available units of a particular kind

Qty.getUnits('currency');// => [ 'dollar', 'cents' ]// Or all alphabetically sortedQty.getUnits();// => [ 'acre','Ah','ampere','AMU','angstrom']

Alternative names of a unit

Qty.getAliases('m');// => [ 'm', 'meter', 'meters', 'metre', 'metres' ]

Quantity compatibility, kind and various queries

qty1.isCompatible(qty2);// => true or falseqty.kind();// => 'length', 'area', etc...qty.isUnitless();// => true or falseqty.isBase();// => true if quantity is represented with base units

Conversion

qty.toBase();// converts to SI units (10 cm => 0.1 m) (new instance)qty.toFloat();// returns scalar of unitless quantity// (otherwise throws error)qty.to('m');// converts quantity to meter if compatible// or throws an error (new instance)qty1.to(qty2);// converts quantity to same unit of qty2 if compatible// or throws an error (new instance)qty.inverse();// converts quantity to its inverse// ('100 m/s' => '.01 s/m')// Inverses can be used, but there is no special checking to// rename the unitsQty('10ohm').inverse()// '.1/ohm'// (not '.1S', although they are equivalent)// however, the 'to' command will convert between inverses alsoQty('10ohm').to('S')// '.1S'

Qty.swiftConverter() is a fast way to efficiently convert large array of Number values. It configures a function accepting a value or an array of Number values to convert.

varconvert=Qty.swiftConverter('m/h','ft/s');// Configures converter// Converting single valuevarconverted=convert(2500);// => 2.278..// Converting large array of valuesvarconvertedSerie=convert([2500,5000, ...]);// => [2.278.., 4.556.., ...]

The main drawback of this conversion method is that it does not take care of rounding issues.

Comparison

qty1.eq(qty2);// => true if both quantities are equal (1m == 100cm => true)qty1.same(qty2);// => true if both quantities are same (1m == 100cm => false)qty1.lt(qty2);// => true if qty1 is stricty less than qty2qty1.lte(qty2);// => true if qty1 is less than or equal to qty2qty1.gt(qty2);// => true if qty1 is stricty greater than qty2qty1.gte(qty2);// => true if qty1 is greater than or equal to qty2qty1.compareTo(qty2);// => -1 if qty1 < qty2,// => 0 if qty1 == qty2,// => 1 if qty1 > qty2

Operators

  • add(other): Add. other can be string or quantity. other should be unit compatible.
  • sub(other): Substract. other can be string or quantity. other should be unit compatible.
  • mul(other): Multiply. other can be string, number or quantity.
  • div(other): Divide. other can be string, number or quantity.

Rounding

Qty#toPrec(precision) : returns the nearest multiple of quantity passed as precision.

varqty=Qty('5.17 ft');qty.toPrec('ft');// => 5 ftqty.toPrec('0.5 ft');// => 5 ftqty.toPrec('0.25 ft');// => 5.25 ftqty.toPrec('0.1 ft');// => 5.2 ftqty.toPrec('0.05 ft');// => 5.15 ftqty.toPrec('0.01 ft');// => 5.17 ftqty.toPrec('0.00001 ft');// => 5.17 ftqty.toPrec('2 ft');// => 6 ftqty.toPrec('2');// => 6 ftvarqty=Qty('6.3782 m');qty.toPrec('dm');// => 6.4 mqty.toPrec('cm');// => 6.38 mqty.toPrec('mm');// => 6.378 mqty.toPrec('5 cm');// => 6.4 mqty.toPrec('10 m');// => 10 mqty.toPrec(0.1);// => 6.3 mvarqty=Qty('1.146 MPa');qty.toPrec('0.1 bar');// => 1.15 MPa

Formatting quantities

Qty#toString returns a string using the canonical form of the quantity (that is it could be seamlessly reparsed by Qty).

varqty=Qty('1.146 MPa');qty.toString();// => '1.146 MPa'

As a shorthand, units could be passed to Qty#toString and is equivalent to successively call Qty#to then Qty#toString.

varqty=Qty('1.146 MPa');qty.toString('bar');// => '11.46 bar'qty.to('bar').toString();// => '11.46 bar'

Qty#toString could also be used with any method from Qty to make some sort of formatting. For instance, one could use Qty#toPrec to fix the maximum number of decimals:

varqty=Qty('1.146 MPa');qty.toPrec(0.1).toString();// => '1.1 MPa'qty.to('bar').toPrec(0.1).toString();// => '11.5 bar'

For advanced formatting needs as localization, specific rounding or any other custom customization, quantities can be transformed into strings through Qty#format according to optional target units and formatter. If target units are specified, the quantity is converted into them before formatting.

Such a string is not intended to be reparsed to construct a new instance of Qty (unlike output of Qty#toString).

If no formatter is specified, quantities are formatted according to default js-quantities' formatter and is equivalent to Qty#toString.

varqty=Qty('1.1234 m');qty.format();// same units, default formatter => '1.234 m'qty.format('cm');// converted to 'cm', default formatter => '123.45 cm'

Qty#format could delegates formatting to a custom formatter if required. A formatter is a callback function accepting scalar and units as parameters and returning a formatted string representing the quantity.

varconfigurableRoundingFormatter=function(maxDecimals){returnfunction(scalar,units){varpow=Math.pow(10,maxDecimals);varrounded=Math.round(scalar*pow)/pow;returnrounded+' '+units;};};varqty=Qty('1.1234 m');// same units, custom formatter => '1.12 m'qty.format(configurableRoundingFormatter(2));// convert to 'cm', custom formatter => '123.4 cm'qty.format('cm',configurableRoundingFormatter(1));

Custom formatter can be configured globally by setting Qty.formatter.

Qty.formatter=configurableRoundingFormatter(2);varqty=Qty('1.1234 m');qty.format();// same units, current default formatter => '1.12 m'

Temperatures

Like ruby-units, JS-quantities makes a distinction between a temperature (which technically is a property) and degrees of temperature (which temperatures are measured in).

Temperature units (i.e., 'tempK') can be converted back and forth, and will take into account the differences in the zero points of the various scales. Differential temperature (e.g., '100 degC') units behave like most other units.

Qty('37 tempC').to('tempF')// => 98.6 tempF

JS-quantities will throw an error if you attempt to create a temperature unit that would fall below absolute zero.

Unit math on temperatures is fairly limited.

Qty('100 tempC').add('10 degC')// 110 tempCQty('100 tempC').sub('10 degC')// 90 tempCQty('100 tempC').add('50 tempC')// throws errorQty('100 tempC').sub('50 tempC')// 50 degCQty('50 tempC').sub('100 tempC')// -50 degCQty('100 tempC').mul(scalar)// 100*scalar tempCQty('100 tempC').div(scalar)// 100/scalar tempCQty('100 tempC').mul(qty)// throws errorQty('100 tempC').div(qty)// throws errorQty('100 tempC*unit')// throws errorQty('100 tempC/unit')// throws errorQty('100 unit/tempC')// throws errorQty('100 tempC').inverse()// throws error
Qty('100 tempC').to('degC')// => 100 degC

This conversion references the 0 point on the scale of the temperature unit

Qty('100 degC').to('tempC')// => -173.15 tempC

These conversions are always interpreted as being relative to absolute zero. Conversions are probably better done like this...

Qty('0 tempC').add('100 degC')// => 100 tempC

Errors

Every error thrown by JS-quantities is an instance of Qty.Error.

try{// code triggering an error inside JS-quantities}catch(e){if(einstanceofQty.Error){// ...}else{// ...}}

Tests

Tests are implemented with Jasmine (https://github.com/pivotal/jasmine). You could use both HTML and jasmine-node runners.

To execute specs through HTML runner, just open SpecRunner.html file in a browser to execute them.

To execute specs through jasmine-node, launch:

make test

Performance regression test

There is a small benchmarking HTML page to spot performance regression between currently checked-out quantities.js and any committed version. Just execute:

make bench

then open http://0.0.0.0:3000/bench

Checked-out version is benchmarked against HEAD by default but it could be changed by passing any commit SHA on the command line. Port (default 3000) is also configurable.

make bench COMMIT=e0c7fc468 PORT=5000

TypeScript type declarations

A TypeScript declaration file is published on DefinitelyTyped.

It could be installed with npm install @types/js-quantities.

Contribute

Feedback and contributions are welcomed.

Pull requests must pass tests and linting. Please make sure that make test and make lint return no errors before submitting.

About

JavaScript library for quantity calculation and unit conversion

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages