diff --git a/README.md b/README.md index 65f0c70..cf84e01 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ npm install node-units * `importDB(file_name, cb)` - imports a custom unit database, `cb` takes a single argument `err` * `importDBSync(file_name)` - the sync version of `importDB` * `getDB()` - returns he currently used database of units as an object +* `getUnitType(unit)` - given a single unit it will return back `{'type': , 'unit': , 'modifier': }` * `convert(conversion_string)` - where `conversion_string` is of the form ` to ` ### Properties @@ -72,6 +73,27 @@ var result = units.convert('5 minutes to s'); // result == 250 ``` +## Values +`node-units` uses `numberizer` which is used to convert string versions of numbers into digits, for example, `forty two` becomes `42` and `one fifth` becomes `0.2`. + +What is currently not supported is mathematical symbols like `1/5 days`. + +## Prefixes + +`node-units` comes with a plethora of built in long and shortname unit prefixes like: +* nano-, n- +* micro-, mu- +* mega- +* giga- +* milli-, m- +* centi-, c- +* and others + +## Variations + +`node-units` also understands that it makes more sense to say things like `five days` rather than `five day` so when a unit is not know it will automatically look if the unit +ends with either `s`, `es` or `ies`. + ## License The MIT License (MIT) diff --git a/examples/custom/index.js b/examples/custom/index.js index c76b27f..5197a8f 100644 --- a/examples/custom/index.js +++ b/examples/custom/index.js @@ -4,7 +4,9 @@ var units = require('../../'); var db = path.join(path.dirname(module.filename), 'my_custom.units'); units.importDBSync(db); -console.log(units.convert('5 buttons to widgets')); +console.dir(units.getUnitType('jong')); +console.dir(units.getUnitType('megajongs')); +console.log(units.convert('5 buttons to widgets')); console.log(units.convert('30 jings to jong')); diff --git a/examples/simple/index.js b/examples/simple/index.js index 4f85b04..4f36dec 100644 --- a/examples/simple/index.js +++ b/examples/simple/index.js @@ -1,10 +1,11 @@ var units = require('../../'); -var result = units.convert('20 quarts to gallons'); +console.dir(units.getUnitType('gallons')); +console.dir(units.getUnitType('milliliters')); +var result = units.convert('20 quarts to gallons'); console.log(result === 5); - try{ var value = units.convert('5 days to gallon'); console.log(value); diff --git a/lib/index.js b/lib/index.js index b1abe82..b7f226c 100644 --- a/lib/index.js +++ b/lib/index.js @@ -11,6 +11,92 @@ var unit_database = {}; var forms = [/s$/i, /es$/i, /ies$/i]; +var short_prefixes = [ + {'pattern': /^da/, + 'modifier': 10}, + {'pattern': /^mu/, + 'modifier': 1e-6}, + {'pattern': /^m/, + 'modifier': 1e-3}, + {'pattern': /^h/, + 'modifier': 100}, + {'pattern': /^k/, + 'modifier': 1000}, + {'pattern': /^M/, + 'modifier': 1e6}, + {'pattern': /^G/, + 'modifier': 1e9}, + {'pattern': /^T/, + 'modifier': 1e12}, + {'pattern': /^P/, + 'modifier': 1e15}, + {'pattern': /^E/, + 'modifier': 1e18}, + {'pattern': /^Z/, + 'modifier': 1e21}, + {'pattern': /^Y/, + 'modifier': 1e24}, + {'pattern': /^n/, + 'modifier': 1e-9}, + {'pattern': /^p/, + 'modifier': 1e-12}, + {'pattern': /^c/, + 'modifier': 1e-2}, + {'pattern': /^d/, + 'modifier': 1e-1}, + {'pattern': /^f/, + 'modifier': 1e-15}, + {'pattern': /^a/, + 'modifier': 1e-18}, + {'pattern': /^z/, + 'modifier': 1e-21}, + {'pattern': /^y/, + 'modifier': 1e-24}, +]; + +var long_prefixes = [ + {'pattern': /^milli/i, + 'modifier': 1e-3}, + {'pattern': /^micro/i, + 'modifier': 1e-6}, + {'pattern': /^nano/i, + 'modifier': 1e-9}, + {'pattern': /^pico/i, + 'modifier': 1e-12}, + {'pattern': /^centi/i, + 'modifier': 1e-2}, + {'pattern': /^deci/i, + 'modifier': 1e-1}, + {'pattern': /^femto/i, + 'modifier': 1e-15}, + {'pattern': /^atto/i, + 'modifier': 1e-18}, + {'pattern': /^zepto/i, + 'modifier': 1e-21}, + {'pattern': /^yocto/i, + 'modifier': 1e-24}, + {'pattern': /^deka/i, + 'modifier': 10}, + {'pattern': /^hecto/i, + 'modifier': 100}, + {'pattern': /^kilo/i, + 'modifier': 1000}, + {'pattern': /^mega/i, + 'modifier': 1e6}, + {'pattern': /^giga/i, + 'modifier': 1e9}, + {'pattern': /^tera/i, + 'modifier': 1e12}, + {'pattern': /^peta/i, + 'modifier': 1e15}, + {'pattern': /^exa/i, + 'modifier': 1e18}, + {'pattern': /^zeta/i, + 'modifier': 1e21}, + {'pattern': /^yotta/i, + 'modifier': 1e24}, +]; + var parseSection = function(section){ var lines = section.split('\n'); var section_name = lines.shift(); @@ -32,8 +118,8 @@ var parseSection = function(section){ value = parseFloat(value[0]); names.forEach(function(name){ - unit_database[section_name][name.toLowerCase()] = {'unit': unit, - 'value': value}; + unit_database[section_name][name] = {'unit': unit, + 'value': value}; }); } }; @@ -61,7 +147,7 @@ var convert = function(type, value, from, to, max_calls){ if(max_calls <= 0){ return undefined; } - var section = unit_database[type.toLowerCase()]; + var section = unit_database[type]; if(!section){ return undefined; } @@ -88,6 +174,10 @@ var convert = function(type, value, from, to, max_calls){ var get_variations = function(unit){ var variations = [unit]; + if(unit.length == 2){ + return variations; + } + forms.forEach(function(form){ if(unit.match(form)){ variations.push(unit.replace(form, '')); @@ -97,11 +187,32 @@ var get_variations = function(unit){ }; +var get_modifier = function(unit){ + var prefixes = short_prefixes; + if(unit.length > 3){ + prefixes = long_prefixes; + } + for(var i in prefixes){ + var prefix = prefixes[i]; + if(unit.match(prefix.pattern)){ + return {'unit': unit.replace(prefix.pattern, ''), + 'modifier': prefix.modifier}; + } + } + return {'unit': unit, + 'modifier': 1}; +}; + var determine_type = function(variations){ for(var i in types){ for(var k in variations){ if(unit_database[types[i]][variations[k]] !== undefined){ - return {'type': types[i], 'unit': variations[k]}; + return {'type': types[i], 'unit': variations[k], 'modifier': 1}; + } else{ + var modified = get_modifier(variations[k]); + if(unit_database[types[i]][modified.unit] !== undefined){ + return {'type': types[i], 'unit': modified.unit, 'modifier': modified.modifier}; + } } } } @@ -117,8 +228,17 @@ return module.exports = { getDB: function(){ return unit_database; }, + getUnitType: function(unit){ + var type = determine_type(get_variations(unit)); + if(!type){ + return null; + } + + return type; + }, convert: function(str){ - var type, value, from, to, max_tries; + var type, value, from, to; + var max_tries = 5; var parts = conversion_regex.exec(str); if(parts == null){ @@ -127,8 +247,8 @@ return module.exports = { } value = parseFloat(numerizer(parts[1])); - var from_variations = get_variations(parts[2].toLowerCase()); - var to_variations = get_variations(parts[3].toLowerCase()); + var from_variations = get_variations(parts[2]); + var to_variations = get_variations(parts[3]); var from_type = determine_type(from_variations); var to_type = determine_type(to_variations); @@ -147,6 +267,7 @@ return module.exports = { return; } + value = value * from_type.modifier; type = from_type.type; from = from_type.unit; to = to_type.unit; @@ -155,7 +276,7 @@ return module.exports = { if(result == undefined){ throw 'Conversion of "' + from + '" to "' + to + '" was not possible'; } else{ - return result; + return result / to_type.modifier; } }, }; diff --git a/package.json b/package.json index a51af27..3ba7718 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-units", - "version": "0.1.1", + "version": "0.1.2", "description": "Node.JS unit conversion library with customizable units", "main": "lib/index.js", "directories": {