315 lines
10 KiB
JavaScript
315 lines
10 KiB
JavaScript
// list of currencies where energy price should be displayed in subunits (factor 100)
|
|
const ENERGY_PRICE_IN_SUBUNIT = {
|
|
AUD: "c", // Australian cent
|
|
BGN: "st", // Bulgarian stotinka
|
|
BRL: "¢", // Brazilian centavo
|
|
CAD: "¢", // Canadian cent
|
|
CHF: "rp", // Swiss Rappen
|
|
CNY: "f", // Chinese fen
|
|
EUR: "ct", // Euro cent
|
|
GBP: "p", // GB pence
|
|
ILS: "ag", // Israeli agora
|
|
NZD: "c", // New Zealand cent
|
|
PLN: "gr", // Polish grosz
|
|
USD: "¢", // US cent
|
|
};
|
|
|
|
export const POWER_UNIT = Object.freeze({
|
|
W: "W",
|
|
KW: "kW",
|
|
MW: "MW",
|
|
AUTO: "",
|
|
});
|
|
|
|
export default {
|
|
data: function () {
|
|
return {
|
|
POWER_UNIT,
|
|
fmtLimit: 100,
|
|
fmtDigits: 1,
|
|
};
|
|
},
|
|
methods: {
|
|
round: function (num, precision) {
|
|
var base = 10 ** precision;
|
|
return (Math.round(num * base) / base).toFixed(precision);
|
|
},
|
|
fmt: function (val) {
|
|
if (val === undefined || val === null) {
|
|
return 0;
|
|
}
|
|
let absVal = Math.abs(val);
|
|
return absVal >= this.fmtLimit
|
|
? this.round(absVal / 1e3, this.fmtDigits)
|
|
: this.round(absVal, 0);
|
|
},
|
|
fmtW: function (watt = 0, format = POWER_UNIT.KW, withUnit = true, digits) {
|
|
let unit = format;
|
|
let d = digits;
|
|
if (POWER_UNIT.AUTO === unit) {
|
|
if (watt >= 10_000_000) {
|
|
unit = POWER_UNIT.MW;
|
|
} else if (watt >= 1000 || 0 === watt) {
|
|
unit = POWER_UNIT.KW;
|
|
} else {
|
|
unit = POWER_UNIT.W;
|
|
}
|
|
}
|
|
let value = watt;
|
|
if (POWER_UNIT.KW === unit) {
|
|
value = watt / 1000;
|
|
} else if (POWER_UNIT.MW === unit) {
|
|
value = watt / 1_000_000;
|
|
}
|
|
if (d === undefined) {
|
|
d = POWER_UNIT.KW === unit || POWER_UNIT.MW === unit || 0 === watt ? 1 : 0;
|
|
}
|
|
return `${new Intl.NumberFormat(this.$i18n?.locale, {
|
|
style: "decimal",
|
|
minimumFractionDigits: d,
|
|
maximumFractionDigits: d,
|
|
}).format(value)}${withUnit ? ` ${unit}` : ""}`;
|
|
},
|
|
fmtWh: function (watt, format = POWER_UNIT.KW, withUnit = true, digits) {
|
|
return this.fmtW(watt, format, withUnit, digits) + (withUnit ? "h" : "");
|
|
},
|
|
fmtNumber: function (number, decimals, unit) {
|
|
const style = unit ? "unit" : "decimal";
|
|
return new Intl.NumberFormat(this.$i18n?.locale, {
|
|
style,
|
|
unit,
|
|
minimumFractionDigits: decimals,
|
|
maximumFractionDigits: decimals,
|
|
}).format(number);
|
|
},
|
|
fmtGrams: function (gramms, withUnit = true) {
|
|
let unit = "gram";
|
|
let value = gramms;
|
|
if (gramms >= 1000) {
|
|
unit = "kilogram";
|
|
value = gramms / 1000;
|
|
}
|
|
return new Intl.NumberFormat(this.$i18n?.locale, {
|
|
style: withUnit ? "unit" : "decimal",
|
|
unit,
|
|
minimumFractionDigits: 0,
|
|
maximumFractionDigits: 0,
|
|
}).format(value);
|
|
},
|
|
fmtCo2Short: function (gramms) {
|
|
return `${this.fmtNumber(gramms, 0)} g`;
|
|
},
|
|
fmtCo2Medium: function (gramms) {
|
|
return `${this.fmtNumber(gramms, 0)} g/kWh`;
|
|
},
|
|
fmtCo2Long: function (gramms) {
|
|
return `${this.fmtNumber(gramms, 0)} gCO₂e/kWh`;
|
|
},
|
|
fmtUnit: function (val) {
|
|
return Math.abs(val) >= this.fmtLimit ? "k" : "";
|
|
},
|
|
fmtNumberToLocale(val, pad = 0) {
|
|
return val.toLocaleString(this.$i18n?.locale).padStart(pad, "0");
|
|
},
|
|
fmtDurationToTime(date) {
|
|
const diff = date - new Date();
|
|
return this.fmtDuration(diff / 1000, true, "h");
|
|
},
|
|
fmtDurationNs(duration = 0, withUnit = true, minUnit = "s") {
|
|
return this.fmtDuration(duration / 1e9, withUnit, minUnit);
|
|
},
|
|
fmtDuration: function (duration = 0, withUnit = true, minUnit = "s") {
|
|
if (duration <= 0) {
|
|
return "—";
|
|
}
|
|
let roundedDuration = Math.round(duration);
|
|
var seconds = roundedDuration % 60;
|
|
var minutes = Math.floor(roundedDuration / 60) % 60;
|
|
var hours = Math.floor(roundedDuration / 3600);
|
|
var result = "";
|
|
let unit = "";
|
|
if (hours >= 1 || minUnit === "h") {
|
|
result = `${this.fmtNumberToLocale(hours)}:${this.fmtNumberToLocale(minutes, 2)}`;
|
|
unit = "h";
|
|
} else if (minutes >= 1 || minUnit === "m") {
|
|
result = `${this.fmtNumberToLocale(minutes)}:${this.fmtNumberToLocale(seconds, 2)}`;
|
|
unit = "m";
|
|
} else {
|
|
result = `${this.fmtNumberToLocale(seconds)}`;
|
|
unit = "s";
|
|
}
|
|
if (withUnit) {
|
|
result += `\u202F${unit}`;
|
|
}
|
|
return result;
|
|
},
|
|
fmtDayString: function (date) {
|
|
const YY = `${date.getFullYear()}`;
|
|
const MM = `${date.getMonth() + 1}`.padStart(2, "0");
|
|
const DD = `${date.getDate()}`.padStart(2, "0");
|
|
return `${YY}-${MM}-${DD}`;
|
|
},
|
|
fmtTimeString: function (date) {
|
|
const HH = `${date.getHours()}`.padStart(2, "0");
|
|
const mm = `${date.getMinutes()}`.padStart(2, "0");
|
|
return `${HH}:${mm}`;
|
|
},
|
|
isToday: function (date) {
|
|
const today = new Date();
|
|
return today.toDateString() === date.toDateString();
|
|
},
|
|
isTomorrow: function (date) {
|
|
const tomorrow = new Date();
|
|
tomorrow.setDate(tomorrow.getDate() + 1);
|
|
return tomorrow.toDateString() === date.toDateString();
|
|
},
|
|
weekdayPrefix: function (date) {
|
|
const rtf = new Intl.RelativeTimeFormat(this.$i18n?.locale, { numeric: "auto" });
|
|
|
|
if (this.isToday(date)) {
|
|
return ""; //rtf.formatToParts(0, "day")[0].value;
|
|
}
|
|
if (this.isTomorrow(date)) {
|
|
return rtf.formatToParts(1, "day")[0].value;
|
|
}
|
|
return new Intl.DateTimeFormat(this.$i18n?.locale, {
|
|
weekday: "short",
|
|
}).format(date);
|
|
},
|
|
weekdayTime: function (date) {
|
|
return new Intl.DateTimeFormat(this.$i18n?.locale, {
|
|
weekday: "short",
|
|
hour: "numeric",
|
|
minute: "numeric",
|
|
}).format(date);
|
|
},
|
|
weekdayShort: function (date) {
|
|
return new Intl.DateTimeFormat(this.$i18n?.locale, {
|
|
weekday: "short",
|
|
}).format(date);
|
|
},
|
|
fmtAbsoluteDate: function (date) {
|
|
const weekday = this.weekdayPrefix(date);
|
|
const hour = new Intl.DateTimeFormat(this.$i18n?.locale, {
|
|
hour: "numeric",
|
|
minute: "numeric",
|
|
}).format(date);
|
|
|
|
return `${weekday} ${hour}`.trim();
|
|
},
|
|
fmtFullDateTime: function (date, short) {
|
|
return new Intl.DateTimeFormat(this.$i18n?.locale, {
|
|
weekday: short ? undefined : "short",
|
|
month: short ? "numeric" : "short",
|
|
day: "numeric",
|
|
hour: "numeric",
|
|
minute: "numeric",
|
|
}).format(date);
|
|
},
|
|
fmtMonthYear: function (date) {
|
|
return new Intl.DateTimeFormat(this.$i18n?.locale, {
|
|
month: "long",
|
|
year: "numeric",
|
|
}).format(date);
|
|
},
|
|
fmtMonth: function (date, short) {
|
|
return new Intl.DateTimeFormat(this.$i18n?.locale, {
|
|
month: short ? "short" : "long",
|
|
}).format(date);
|
|
},
|
|
fmtYear: function (date) {
|
|
return new Intl.DateTimeFormat(this.$i18n?.locale, {
|
|
year: "numeric",
|
|
}).format(date);
|
|
},
|
|
fmtDayMonthYear: function (date) {
|
|
return new Intl.DateTimeFormat(this.$i18n?.locale, {
|
|
day: "numeric",
|
|
month: "long",
|
|
year: "numeric",
|
|
}).format(date);
|
|
},
|
|
fmtDayMonth: function (date) {
|
|
return new Intl.DateTimeFormat(this.$i18n?.locale, {
|
|
weekday: "short",
|
|
day: "numeric",
|
|
month: "short",
|
|
}).format(date);
|
|
},
|
|
fmtMoney: function (amout = 0, currency = "EUR", decimals = true, withSymbol = false) {
|
|
const currencyDisplay = withSymbol ? "narrowSymbol" : "code";
|
|
const result = new Intl.NumberFormat(this.$i18n?.locale, {
|
|
style: "currency",
|
|
currency,
|
|
currencyDisplay,
|
|
maximumFractionDigits: decimals ? undefined : 0,
|
|
}).format(amout);
|
|
|
|
return withSymbol ? result : result.replace(currency, "").trim();
|
|
},
|
|
fmtCurrencySymbol: function (currency = "EUR") {
|
|
const symbols = { EUR: "€", USD: "$" };
|
|
return symbols[currency] || currency;
|
|
},
|
|
fmtPricePerKWh: function (amout = 0, currency = "EUR", short = false, withUnit = true) {
|
|
let value = amout;
|
|
let minimumFractionDigits = 1;
|
|
let maximumFractionDigits = 3;
|
|
if (ENERGY_PRICE_IN_SUBUNIT[currency]) {
|
|
value *= 100;
|
|
minimumFractionDigits = 1;
|
|
maximumFractionDigits = 1;
|
|
}
|
|
const price = new Intl.NumberFormat(this.$i18n?.locale, {
|
|
style: "decimal",
|
|
minimumFractionDigits,
|
|
maximumFractionDigits,
|
|
}).format(value);
|
|
if (withUnit) {
|
|
return `${price} ${this.pricePerKWhUnit(currency, short)}`;
|
|
}
|
|
return price;
|
|
},
|
|
pricePerKWhUnit: function (currency = "EUR", short = false) {
|
|
const unit = ENERGY_PRICE_IN_SUBUNIT[currency] || currency;
|
|
return `${unit}${short ? "" : "/kWh"}`;
|
|
},
|
|
fmtTimeAgo: function (elapsed) {
|
|
const units = {
|
|
day: 24 * 60 * 60 * 1000,
|
|
hour: 60 * 60 * 1000,
|
|
minute: 60 * 1000,
|
|
second: 1000,
|
|
};
|
|
|
|
const rtf = new Intl.RelativeTimeFormat(this.$i18n?.locale, { numeric: "auto" });
|
|
|
|
// "Math.abs" accounts for both "past" & "future" scenarios
|
|
for (var u in units)
|
|
if (Math.abs(elapsed) > units[u] || u == "second")
|
|
return rtf.format(Math.round(elapsed / units[u]), u);
|
|
},
|
|
fmtSocOption: function (soc, rangePerSoc, distanceUnit, heating) {
|
|
let result = heating ? this.fmtTemperature(soc) : `${this.fmtPercentage(soc)}`;
|
|
if (rangePerSoc && distanceUnit) {
|
|
const range = soc * rangePerSoc;
|
|
result += ` (${this.fmtNumber(range, 0)} ${distanceUnit})`;
|
|
}
|
|
return result;
|
|
},
|
|
fmtPercentage: function (value, digits = 0) {
|
|
return new Intl.NumberFormat(this.$i18n?.locale, {
|
|
style: "percent",
|
|
minimumFractionDigits: digits,
|
|
maximumFractionDigits: digits,
|
|
}).format(value / 100);
|
|
},
|
|
hasLeadingPercentageSign: function () {
|
|
return ["tr", "ar"].includes(this.$i18n?.locale);
|
|
},
|
|
fmtTemperature: function (value) {
|
|
// TODO: handle fahrenheit
|
|
return this.fmtNumber(value, 1, "celsius");
|
|
},
|
|
},
|
|
};
|