Comments (2)
I did some work around.
Here is an implementation outside of the lib.
It is probably very specific use case, but if you would like to provide on your side a shiftUnit
and something like getUnitPlace
, it would be very useful to reduce the size of such code.
If you like that idea, i can create a pull request.
const PREFIX = {
'<tera>': 12,
'<giga>': 9,
'<mega>': 6,
'<kilo>': 3,
'<1>': 0,
'<milli>': -3,
'<micro>': -6,
'<nano>': -9
};
const PLACES_TO_PREFIX = {};
for (const [key, value] of Object.entries(PREFIX)) {
PLACES_TO_PREFIX[value] = key;
}
/**
* Returns a quantity with a unit inside a readable range of values
*
* The prefix of the unit (n/u/k/M) is picked to make the value
* in the range 0.1 .. 999
*/
export function toHumanReadableUnit(quantity) {
if (quantity.scalar === 0) {
return quantity;
}
function getNextDeltaPlace(q) {
const v = q.scalar;
if (v > 200) {
return 3;
}
if (v < 0.3) {
return -3;
}
return 0;
}
function getUnitWithNewPrefix(q, prefix) {
function cleanup(elemString) {
if (elemString === undefined) return '';
if (elemString === '<1>') return '';
return elemString.substring(1, elemString.length - 1);
}
let n = '';
for (let ni = 0; ni < q.numerator.length; ni += 1) {
const elem = q.numerator[ni];
if (ni === 0) {
const notPrefix = PREFIX[elem] === undefined;
n += cleanup(prefix) + (notPrefix ? cleanup(elem) : '');
} else {
n += cleanup(elem);
}
}
let d = '';
for (let di = 0; di < q.denominator.length; di += 1) {
const elem = q.denominator[di];
d += cleanup(elem);
}
if (d === '') {
return n;
}
if (n === '') {
return `1/${d}`;
}
return `${n}/${d}`;
}
function getCurrentPlace(q) {
return PREFIX[q.numerator[0]] || 0;
}
function shiftUnit(q, deltaPlace) {
const place = getCurrentPlace(q) + deltaPlace;
const prefixNumerator = PLACES_TO_PREFIX[place];
if (prefixNumerator === undefined) {
return q;
}
const unit = getUnitWithNewPrefix(quantity, prefixNumerator);
return q.to(unit);
}
let current = quantity;
for (let i = 0; i < 10; i += 1) {
const deltaPlace = getNextDeltaPlace(current);
if (deltaPlace === 0) {
break;
}
current = shiftUnit(current, deltaPlace);
}
// Check if we loose a bit of digits
const fixed = current.scalar.toFixed(2);
if (
fixed.length === 4 &&
fixed.substring(0, 2) === '0.' &&
fixed.substring(3, 4) !== '0'
) {
return shiftUnit(current, -3);
}
return current;
}
import Qty from 'js-quantities';
import { toHumanReadableUnit } from 'helpers/QtyHelper';
describe('Qty helper', () => {
test('check already normalized', async () => {
const q = Qty('10 mm');
const result = toHumanReadableUnit(q);
expect(result.toPrec(0.1).toString()).toEqual('10 mm');
});
test('check with smaller unit than expected', async () => {
const q = Qty('1000 mm');
const result = toHumanReadableUnit(q);
expect(result.toPrec(0.1).toString()).toEqual('1 m');
});
test('check with bigger unit than expected', async () => {
const q = Qty('0.02 mm');
const result = toHumanReadableUnit(q);
expect(result.toPrec(0.1).toString()).toEqual('20 um');
});
test('check with smaller unit than expected', async () => {
const q = Qty('0.0222 mm');
const result = toHumanReadableUnit(q);
expect(result.toPrec(0.1).toString()).toEqual('22.2 um');
});
test('check with more than 2 precision digit', async () => {
const q = Qty('0.222 mm');
const result = toHumanReadableUnit(q);
expect(result.toPrec(0.1).toString()).toEqual('222 um');
});
test('check with a value bigger than 200', async () => {
const q = Qty('0.500 mm');
const result = toHumanReadableUnit(q);
expect(result.toPrec(0.1).toString()).toEqual('0.5 mm');
});
test('check above rounding error', async () => {
const q = Qty('0.995 mm');
const result = toHumanReadableUnit(q);
expect(result.toPrec(0.1).toString()).toEqual('995 um');
});
test('check under rounding error', async () => {
const q = Qty('0.996 mm');
const result = toHumanReadableUnit(q);
expect(result.toPrec(0.1).toString()).toEqual('1 mm');
});
});
from js-quantities.
Duplicate of #87 ?
from js-quantities.
Related Issues (20)
- getSystems() It would be useful to tag/group the unit names by their SI, Imperial or other system and allow conversion toSystem('imperial')
- Possibility to add a method qty.getUnit() ? HOT 1
- Dividing by temperatures HOT 1
- Dividing by temperature HOT 1
- add metric ton symbol "t" HOT 1
- surfaces (m², km², hectares) HOT 1
- compatibility with Unified Code for Units of Measure HOT 1
- Translation of units into different languages
- no power operators? HOT 1
- js-quantities is incompatible with sugarjs and prototypejs
- Lacking precision necessary for required comparisons HOT 10
- No converter for Miliradians
- Swift Converter error: Incompatible units
- Values formatted with group separators do not parse
- Pretty unit output
- Publish new version to npm HOT 1
- Can't import the ES module in Angular HOT 4
- Rounding Issues when converting Millimeter to Centimeter HOT 3
- Can't convert nautical miles to meters correctly HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from js-quantities.