Unit of Measure Conversion Library

前端 未结 8 2150
面向向阳花
面向向阳花 2020-12-07 15:15

What is the best/most elegant way to abstract out the conversion of units of measures in the client, based on a user-preferred unit of measure setting?

For example,

相关标签:
8条回答
  • 2020-12-07 15:29

    How many different units are being converted? It sounds as though you are writing an specific application which I'm taking as you only need a few different types of conversion (area, volume, etc)

    If this is the case, it might be faster just to look up the conversion for those that you need and code them into a class for yourself. Loading a complete javascript library just to perform a few specific multiplications could be overkill.

    0 讨论(0)
  • 2020-12-07 15:35

    Inspired by many posts regarding this subject and the simplicity and smallness of MomentJs i have started work on this:

    MeasurementJs

    It doesn't include all of the mentioned conversions yet, but you can easily extend the DEFINITIONS array and MeasurementJs.Units.* objects for any possible conversion you like.

    0 讨论(0)
  • 2020-12-07 15:35

    I'll just leave this here ...

    Simple JS Method to Convert almost ALL Imperial/Standard measurements of Distance/Length

    ;;if (!window.hasOwnProperty('convertImperialMetric')) {
        function convertImperialMetric () {
            var metrics = convertImperialMetric.metrics,
                imperials = convertImperialMetric.imperials,
                args = arguments,
                conversionTypes = { imperial: 'imperial', metric: 'metric' },
                toFixed = false, toFixedX = 2,
                intX, typImp, typMet, conType = 'metric',
                $ret;
    
            conversionTypes.i = conversionTypes.imp = conversionTypes.imperial;
            conversionTypes.m = conversionTypes.met = conversionTypes.metric;
    
            function setVarz(c) {
                for (i in c) {
                    var a = c[i];
                    switch (typeof a) {
                        case "boolean":
                            toFixed = a;
                            break;
                        case "number":
                            void 0 == intX ? intX = a : toFixedX = a;
                            break;
                        case "string":
                            isNaN(parseFloat(a)) || void 0 != intX ? imperials.hasOwnProperty(a) ? typImp = a : metrics.hasOwnProperty(a) ? typMet = a : conversionTypes.hasOwnProperty(a) && (conType = conversionTypes[a]) : intX = parseFloat(a);
                            break;
                        case "object":
                            if (a instanceof Array) setVarz.apply(this, [a]);
                            else if (a instanceof Object)
                                for (h in a) {
                                    var b = a[h];
                                    conversionTypes.hasOwnProperty(h) ? conType = conversionTypes[h] : imperials.hasOwnProperty(h) ? (typImp =
                                        h, void 0 != intX || isNaN(parseFloat(b)) || (intX = parseFloat(b))) : metrics.hasOwnProperty(h) ? (typMet = h, void 0 != intX || isNaN(parseFloat(b)) || (intX = parseFloat(b))) : setVarz.apply(this, [
                                        [b]
                                    ])
                                }
                    }
                }
            };
            setVarz(args);
    
            if (!isNaN(parseFloat(intX)) && imperials.hasOwnProperty(typImp) && metrics.hasOwnProperty(typMet) && conversionTypes.hasOwnProperty(conType)) {
                if (conType == 'metric') {
                    var inches = intX * imperials[typImp],
                        centimeters = inches * 2.54;
                    $ret = centimeters * metrics[typMet];
                }
                else if (conType == 'imperial') {
                    var centimeters = intX / metrics[typMet],
                        inches = centimeters / 2.54;
                    $ret = inches / imperials[typImp];
                }
            }
    
            return toFixed ? parseFloat($ret.toFixed(toFixedX)) : $ret;
        }
    
        convertImperialMetric.imperials = {
            inches: 1,
            feet: 12,
            yards: 36,
            miles: 63360,
            nautical: 72913.4
        };
    
        convertImperialMetric.metrics = {
            yocto: 10000000000000000000000,
            zepto: 10000000000000000000,
            atto: 10000000000000000,
            femto: 10000000000000,
            pico: 10000000000,
            nano: 10000000,
            micro: 10000,
            milli: 10,
            centi: 1,
            deci: .1,
            meter: .01,
            deka: .001,
            hecto: .0001,
            kilo: .00001,
            mega: .00000001,
            giga: .00000000001,
            tera: .00000000000001,
            peta: .00000000000000001,
            exa: .00000000000000000001,
            zetta: .00000000000000000000001,
            yotta: .00000000000000000000000001
        };
    }
    

    Example Usages:

    convertImperialMetric(12, 'inches', 'centi');   //  Results in: 30.48
    convertImperialMetric(30.48, 'centi', 'inches', 'i');   //  Results in: 12
    convertImperialMetric('1200000', 'inches', 'kilo'); //  Results in: 30.480000000000004
    convertImperialMetric('1200000', 'inches', 'kilo', true);   //  Results in: 30.48
    convertImperialMetric('1200000', 'inches', 'kilo', true, 1);    //  Results in: 30.5
    convertImperialMetric([ 12, 'inches', 'centi' ]);   //  Results in: 30.48
    convertImperialMetric([ '12', 'inches', 'centi' ]); //  Results in: 30.48
    convertImperialMetric({ inches: 12, anyVariableName: 'centi' });    //  Results in: 30.48
    convertImperialMetric({ inches: '12', anyVariableName: 'centi' });  //  Results in: 30.48
    convertImperialMetric({ inches: 12, centi: 'anyValue' });   //  Results in: 30.48
    convertImperialMetric({ inches: '12', centi: 'anyValue' }); //  Results in: 30.48
    convertImperialMetric({ inches: '12', to: 'centi', type: 'metric', toFixed: true, toFX: 1 });   //  Results in: 30.5
    convertImperialMetric({ feet: 1 }, 'centi');    //  Results in: 30.48
    convertImperialMetric({ centi: '30.48' }, 'inches', 'imperial');    //  Results in: 12
    convertImperialMetric({ meter: '.3048' }, 'inches', 'imperial');    //  Results in: 12
    

    jsFiddle / jsFiddle/show

    0 讨论(0)
  • 2020-12-07 15:35

    A popular utility that lets you convert between different units: convert-units

    Usage example, converting imperial inches to metric cm:

    var convert = require('convert-units')
    convert(1).from('in').to('cm') // 2.54 
    

    To install:

    npm install convert-units
    
    0 讨论(0)
  • 2020-12-07 15:42

    Here's a little script I threw together just for the heck of it. It handles all the SI conversions for grams, bytes, meters and liters, and also I've added ounces and pounds as an example of non-SI units. To add more, you'll need to:

    1. Add the base type to the "units" list for items that follow SI or
    2. Add the conversion ratios for items that don't follow SI

    Usage:

    $u(1, 'g').as('kg').val(); // converts one gram to kg
    

    You can get the value out with .val(), a string representation using .toString() or the full details via .debug()

    (function () {
        var table = {};
    
        window.unitConverter = function (value, unit) {
            this.value = value;
            if (unit) {
                this.currentUnit = unit;
            }
        };
        unitConverter.prototype.as = function (targetUnit) {
            this.targetUnit = targetUnit;
            return this;
        };
        unitConverter.prototype.is = function (currentUnit) {
            this.currentUnit = currentUnit;
            return this;
        };
    
        unitConverter.prototype.val = function () {
            // first, convert from the current value to the base unit
            var target = table[this.targetUnit];
            var current = table[this.currentUnit];
            if (target.base != current.base) {
                throw new Error('Incompatible units; cannot convert from "' + this.currentUnit + '" to "' + this.targetUnit + '"');
            }
    
            return this.value * (current.multiplier / target.multiplier);
        };
        unitConverter.prototype.toString = function () {
            return this.val() + ' ' + this.targetUnit;
        };
        unitConverter.prototype.debug = function () {
            return this.value + ' ' + this.currentUnit + ' is ' + this.val() + ' ' + this.targetUnit;
        };
        unitConverter.addUnit = function (baseUnit, actualUnit, multiplier) {
            table[actualUnit] = { base: baseUnit, actual: actualUnit, multiplier: multiplier };
        };
    
        var prefixes = ['Y', 'Z', 'E', 'P', 'T', 'G', 'M', 'k', 'h', 'da', '', 'd', 'c', 'm', 'u', 'n', 'p', 'f', 'a', 'z', 'y'];
        var factors = [24, 21, 18, 15, 12, 9, 6, 3, 2, 1, 0, -1, -2, -3, -6, -9, -12, -15, -18, -21, -24];
        // SI units only, that follow the mg/kg/dg/cg type of format
        var units = ['g', 'b', 'l', 'm'];
    
        for (var j = 0; j < units.length; j++) {
            var base = units[j];
            for (var i = 0; i < prefixes.length; i++) {
                unitConverter.addUnit(base, prefixes[i] + base, Math.pow(10, factors[i]));
            }
        }
    
        // we use the SI gram unit as the base; this allows
        // us to convert between SI and English units
        unitConverter.addUnit('g', 'ounce', 28.3495231);
        unitConverter.addUnit('g', 'oz', 28.3495231);
        unitConverter.addUnit('g', 'pound', 453.59237);
        unitConverter.addUnit('g', 'lb', 453.59237);
    
    
        window.$u = function (value, unit) {
            var u = new window.unitConverter(value, unit);
            return u;
        };
    })();
    
    console.log($u(1, 'g').as('kg').debug());  
    console.log($u(1, 'kg').as('g').debug());
    console.log($u(1, 'g').as('mg').debug());
    console.log($u(1, 'mg').as('g').debug());
    console.log($u(1, 'mg').as('kg').debug());
    
    console.log($u(1, 'g').as('oz').debug());
    console.log($u(1, 'g').as('lb').debug());
    
    console.log($u(1, 'oz').as('lb').debug());
    
    console.log($u(1, 'lb').as('g').debug());
    
    // this last one throws an exception since you can't convert liters to mg
    console.log($u(1, 'l').as('mg').debug());
    

    I've moved this to a small repo on Github so if anyone wants to improve/enhance they can do so: https://github.com/jerodvenemafm/jsunitconverter

    0 讨论(0)
  • 2020-12-07 15:46

    The library "measure" converts between unit types (volume, mass, etc.) and supports multiple unit systems (US, Imperial, Metric)

    // volume
    measure('1 teaspoon').teaspoons() // 1
    measure('1 1/2 tsp.').teaspoons() // 1.5
    measure('2 cups and 1 pint').quarts() // 1
    
    // mass
    measure('1 pound').ounces() // 16
    measure('1 1/2 oz.').ounces() // 1.5
    
    // operations
    measure('1 teaspoon').add('1 teaspoon').teaspoons();
    measure('6 1/2 teaspoon').divide(2).teaspoons(); // 3.25
    

    https://github.com/dubbs/measure

    0 讨论(0)
提交回复
热议问题