type Money = { currency: string; value: string }; type FormatMoneyOptions = { withZeroCents?: boolean; }; function formatDecimal(value: string): string { const [integer, fraction] = value.split("."); const sign = integer.startsWith("-") ? "-" : ""; const grouped = (sign ? integer.slice(1) : integer).replace( /\B(?=(\d{3})+(?!\d))/g, " ", ); return `${sign}${grouped}${fraction ? `,${fraction}` : ""}`; } function formatMoney( money: Money | null, { withZeroCents = false }: FormatMoneyOptions = {}, ): string { if (!money) return "—"; const [integerPart, fractionPart = ""] = money.value.split("."); const normalizedFraction = withZeroCents && !fractionPart ? "00" : withZeroCents && fractionPart.length === 1 ? `${fractionPart}0` : fractionPart; return `${formatDecimal( `${integerPart}${normalizedFraction ? `.${normalizedFraction}` : ""}`, )} ${money.currency === "RUB" ? "₽" : money.currency}`; } function formatDate(value: string): string { return new Intl.DateTimeFormat("ru-RU", { day: "2-digit", month: "2-digit", year: "numeric", timeZone: "UTC", }).format(new Date(value)); } function formatSnapshotTime(value: string): string { return new Intl.DateTimeFormat("ru-RU", { dateStyle: "short", timeStyle: "short", timeZone: "UTC", }).format(new Date(value)); } const logoSize = 160; function instrumentLogoUrl(logoName: string | null | undefined): string | null { const stem = logoName?.trim().replace(/\.png$/i, ""); return stem ? `https://invest-brands.cdn-tinkoff.ru/${stem}x${logoSize}.png` : null; } export { formatDate, formatDecimal, formatMoney, formatSnapshotTime, instrumentLogoUrl, };