Converting length in JavaScript - imperial and metric units
Today, we will do some length conversion in JavaScript. We will cover the metric and the imperial systems. When we are done, we will have created our own utility function for converting units between each other.
Metric
As a swede, I am most familiar with the metric system. So we will begin with millimeter, centimeter, meter and kilometer.
Set up
We will begin with creating our metric table. Our base will be meter. At the top of the file, add following object:
const METRIC_UNITS = { KM: { name: "kilometer", factor: 1000 }, M: { name: "meter", factor: 1 }, CM: { name: "centimeter", factor: 0.01 }, MM: { name: "millimeter", factor: 0.001 }, };
So our table will use meter as our baseline. And the factor will represent how many meters 1 of the units represents. So 1km = 1000m, 1cm = 0.01m and so on.
Next, we will create our utility function for converting the units. We will start by getting the meter representation of the value we want to convert from, so that we can easily calculate the result.
convertUnits(from, to, amount) { const meterRepresentation = from.factor * amount }
What we are doing here, is passing in a from unit, a to unit and the amount we want to convert. We are then converting the from value to the metric representation.
Next, we will do the calculation from the metric representation to the new unit. From here, we can simply divide the metric representation with the factor of the new unit.
const result = meterRepresentation / to.factor;
Full code:
const METRIC_UNITS = { KM: { name: "kilometer", factor: 1000 }, M: { name: "meter", factor: 1 }, CM: { name: "centimeter", factor: 0.01 }, MM: { name: "millimeter", factor: 0.001 }, }; const convertUnits = (from, to, amount) => { const meterRepresentation = from.factor * amount; const result = meterRepresentation / to.factor; console.log(`${amount} ${from.name} = ${result} ${to.name}`); return result; };
Test our function
Let's do some tests of our function
const converter = new LengthConverter(); converter.convertUnits(METRIC_UNITS.KM, METRIC_UNITS.M, 1); converter.convertUnits(METRIC_UNITS.M, METRIC_UNITS.CM, 1); converter.convertUnits(METRIC_UNITS.M, METRIC_UNITS.MM, 5); // 1 kilometer = 1000 meter // 1 meter = 100 centimeter // 5 meter = 5000 millimeter
There we go.
Imperial
Let's extend our logic with bringing in some units from the imperial system. The logic will be the same, meaning we will use meter as our base.
Create a new object with the new units
const IMPERIAL_UNITS = { MI: { name: "mile", factor: 1609.3 }, YD: { name: "yard", factor: 0.9144 }, FT: { name: "feet", factor: 0.3048 }, IN: { name: "inch", factor: 0.0254 }, };
And now, our first function should be ready for these values as well, since we are using meter as base.
Let's test
We will now test our conversion, and see if it works across the systems
convertUnits(METRIC_UNITS.KM, IMPERIAL_UNITS.MI, 5); convertUnits(IMPERIAL_UNITS.FT, METRIC_UNITS.CM, 15); convertUnits(METRIC_UNITS.MM, IMPERIAL_UNITS.IN, 25); // 5 kilometer = 3.106940905983968 mile // 15 feet = 457.2 centimeter // 25 millimeter = 0.9842519685039371 inch
Cool, it works!
Clean up the code
So, we generally don't want our result to be a 5 meter (:D) long number with a lot of decimals. So let's round the numbers to maximum 3 decimals.
const result = Math.round((meterRepresentation / to.factor) * 1000) / 1000;
And now our print looks like this instead.
5 kilometer = 3.107 mile 15 feet = 457.2 centimeter 25 millimeter = 0.984 inch
Make it more usable
In order to make our code a little bit more user friendly for our co-workers that will use our cool function, we can make the function accept a string instead of the object
So to use the function, we want our consumers to call it like this
convertUnits("kilometer", "mile", 5); convertUnits("feet", "centimeter", 15); convertUnits("millimeter", "inch", 25); convertUnits("some-faulty-value", "inch", 2000); // 5 kilometer = 3.107 mile // 15 feet = 457.2 centimeter // 25 millimeter = 0.984 inch // No unit exists with name some-faulty-value
Here is the final code of our convertUnits function
const convertUnits = (fromUnit, toUnit, amount) => { const find = (unitName) => Object.values({ ...METRIC_UNITS, ...IMPERIAL_UNITS }).find( (unit) => unit.name === unitName ); const from = find(fromUnit); const to = find(toUnit); if (!from) { console.error(`No unit exists with name ${fromUnit}`); return -1; } else if (!to) { console.error(`No unit exists with name ${toUnit}`); return -1; } const meterRepresentation = from.factor * amount; const result = Math.round((meterRepresentation / to.factor) * 1000) / 1000; console.log(`${amount} ${from.name} = ${result} ${to.name}`); return result; };
In above example, we created a function within our convertUnits function that will basically find the correct unit. Read more on spread operators here if this part
Object.values({ ...METRIC_UNITS, ...IMPERIAL_UNITS });
looks strange to you.
And if some of the units cannot be found, we are returning -1 and printing an error message in the console.
Outro
I will end this tutorial here, with the hope that you learnt more about how we can convert length units between the metric and imperial systems, but also between the units within each system. Thanks for reading, and have a great day.
All the best,