Source code

Revision control

Copy as Markdown

Other Tools

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const ABSOLUTE = ["celsius", "kelvin", "fahrenheit"];
const ALIAS = ["c", "k", "f"];
const UNITS = [...ABSOLUTE, ...ALIAS];
const NUMBER_REGEX = "-?\\d+(?:\\.\\d+)?\\s*";
const UNIT_REGEX = "\\w+";
// NOTE: This regex need to be localized upon supporting multi locales
// since it supports en-US input format only.
const QUERY_REGEX = new RegExp(
`^(${NUMBER_REGEX})(${UNIT_REGEX})(?:\\s+in\\s+|\\s+to\\s+|\\s*=\\s*)(${UNIT_REGEX})`,
"i"
);
const DECIMAL_PRECISION = 10;
/**
* This module converts temperature unit.
*/
export class UnitConverterTemperature {
/**
* Convert the given search string.
*
* @param {string} searchString
* The string to be converted
* @returns {string} conversion result.
*/
convert(searchString) {
const regexResult = QUERY_REGEX.exec(searchString);
if (!regexResult) {
return null;
}
const target = findUnits(regexResult[2], regexResult[3]);
if (!target) {
return null;
}
const { inputUnit, outputUnit } = target;
const inputNumber = Number(regexResult[1]);
const inputChar = inputUnit.charAt(0);
const outputChar = outputUnit.charAt(0);
let outputNumber;
if (inputChar === outputChar) {
outputNumber = inputNumber;
} else {
outputNumber = this[`${inputChar}2${outputChar}`](inputNumber);
}
outputNumber = parseFloat(outputNumber.toPrecision(DECIMAL_PRECISION));
try {
return new Intl.NumberFormat("en-US", {
style: "unit",
unit: outputUnit,
maximumFractionDigits: DECIMAL_PRECISION,
}).format(outputNumber);
} catch (e) {}
return `${outputNumber} ${outputUnit}`;
}
c2k(t) {
return t + 273.15;
}
c2f(t) {
return t * 1.8 + 32;
}
k2c(t) {
return t - 273.15;
}
k2f(t) {
return this.c2f(this.k2c(t));
}
f2c(t) {
return (t - 32) / 1.8;
}
f2k(t) {
return this.c2k(this.f2c(t));
}
}
/**
* Returns the suitable units for the given two values.
* If could not found suitable unit, returns null.
*
* @param {string} inputUnit
* A set of units to convert, mapped to the `inputUnit` value on the return
* @param {string} outputUnit
* A set of units to convert, mapped to the `outputUnit` value on the return
* @returns {{ inputUnit: string, outputUnit: string }} The suitable units.
*/
function findUnits(inputUnit, outputUnit) {
inputUnit = inputUnit.toLowerCase();
outputUnit = outputUnit.toLowerCase();
if (!UNITS.includes(inputUnit) || !UNITS.includes(outputUnit)) {
return null;
}
return {
inputUnit: toAbsoluteUnit(inputUnit),
outputUnit: toAbsoluteUnit(outputUnit),
};
}
function toAbsoluteUnit(unit) {
if (unit.length !== 1) {
return unit;
}
return ABSOLUTE.find(a => a.startsWith(unit));
}