98 lines
2.2 KiB
TypeScript
98 lines
2.2 KiB
TypeScript
const DECIMAL_PART_COUNT = 2;
|
|
const CENTS_PRECISION = 2;
|
|
|
|
type FormatMoneyOptions = {
|
|
withZeroCents?: boolean;
|
|
};
|
|
|
|
type Money = { currency: string; value: string };
|
|
|
|
const dateFormatter = new Intl.DateTimeFormat("ru-RU", {
|
|
day: "2-digit",
|
|
month: "2-digit",
|
|
timeZone: "UTC",
|
|
year: "numeric",
|
|
});
|
|
|
|
function formatDate(value: string): string {
|
|
return dateFormatter.format(new Date(value));
|
|
}
|
|
|
|
function formatDecimal(value: string): string {
|
|
const [integer = "", fraction] = value.split(".", DECIMAL_PART_COUNT);
|
|
const sign = integer.startsWith("-") ? "-" : "";
|
|
const digits = sign ? integer.slice(1) : integer;
|
|
const groupSize = 3;
|
|
const groups: string[] = [];
|
|
|
|
for (let end = digits.length; end > 0; end -= groupSize) {
|
|
groups.push(digits.slice(Math.max(0, end - groupSize), end));
|
|
}
|
|
|
|
const grouped = groups.toReversed().join(" ");
|
|
const suffix = fraction ? `,${fraction}` : "";
|
|
|
|
return `${sign}${grouped}${suffix}`;
|
|
}
|
|
|
|
function formatMoney(
|
|
money: Money
|
|
| null
|
|
| undefined,
|
|
{ withZeroCents = false }: FormatMoneyOptions = {},
|
|
): string {
|
|
if (!money) return "—";
|
|
|
|
const [integerPart = "", fractionPart = ""] = money.value.split(
|
|
".",
|
|
DECIMAL_PART_COUNT,
|
|
);
|
|
|
|
const normalizedFraction = withZeroCents
|
|
? fractionPart.padEnd(CENTS_PRECISION, "0")
|
|
: fractionPart;
|
|
|
|
const decimal = normalizedFraction
|
|
? `${integerPart}.${normalizedFraction}`
|
|
: integerPart;
|
|
|
|
const currency = money.currency === "RUB" ? "₽" : money.currency;
|
|
|
|
return `${formatDecimal(decimal)} ${currency}`;
|
|
}
|
|
|
|
const snapshotFormatter = new Intl.DateTimeFormat("ru-RU", {
|
|
dateStyle: "short",
|
|
timeStyle: "short",
|
|
timeZone: "UTC",
|
|
});
|
|
|
|
function formatSnapshotTime(value: string): string {
|
|
return snapshotFormatter.format(new Date(value));
|
|
}
|
|
|
|
const logoSize = 160;
|
|
|
|
const chartFormatter = new Intl.NumberFormat("ru-RU", { maximumFractionDigits: 4 });
|
|
|
|
function formatChartValue(value: number) {
|
|
return chartFormatter.format(value);
|
|
}
|
|
|
|
function instrumentLogoUrl(logoName?: null | string): null | string {
|
|
const stem = logoName?.trim().replace(/\.png$/i, "");
|
|
|
|
return stem
|
|
? `https://invest-brands.cdn-tinkoff.ru/${stem}x${logoSize}.png`
|
|
: null;
|
|
}
|
|
|
|
export {
|
|
formatChartValue,
|
|
formatDate,
|
|
formatDecimal,
|
|
formatMoney,
|
|
formatSnapshotTime,
|
|
instrumentLogoUrl,
|
|
};
|