Formatlash
Son, so'm, telefon, karta, sana, nisbiy vaqt va fayl hajmini formatlash.
O'zbekistonda odatiy ko'rinishlar standart holatda: 1 250 000 so'm, +998 90 123 45 67,
21 Oktabr 2026, Chorshanba, 5 daqiqa oldin. Funksiyalar Intl va brauzer locale'iga
bog'liq emas — natija serverda ham, har qanday brauzerda ham bir xil. Noto'g'ri kirishda xato
otilmaydi, bo'sh satr '' qaytadi.
import {
formatNumber,
formatMoney,
formatPhone,
formatCardNumber,
formatDate,
parseDate,
timeAgo,
formatFileSize,
} from '@akhatmirzo/core';Son va pul
- formatNumber(n)
- 1 250 000.5
- formatNumber(n, { decimals: 2 })
- 1 250 000.50
- formatMoney(n, { currency })
- 1 250 001 so'm
'use client';
import { formatMoney, formatNumber, type MoneyCurrency } from '@akhatmirzo/core';
import { Button, Field, Input } from '@akhatmirzo/ui';
import { useState } from 'react';
const CURRENCIES: MoneyCurrency[] = ["so'm", 'UZS', false];
export default function CoreMoney() {
const [raw, setRaw] = useState('1250000.5');
const [currency, setCurrency] = useState<MoneyCurrency>("so'm");
const n = Number(raw.replace(',', '.').replace(/\s/g, ''));
const rows = [
{ call: 'formatNumber(n)', value: formatNumber(n) },
{ call: 'formatNumber(n, { decimals: 2 })', value: formatNumber(n, { decimals: 2 }) },
{ call: 'formatMoney(n, { currency })', value: formatMoney(n, { currency }) },
];
return (
<div className="flex w-full max-w-md flex-col gap-4">
<Field label="Son">
<Input value={raw} onChange={(e) => setRaw(e.target.value)} inputMode="decimal" />
</Field>
<div className="flex flex-wrap items-center gap-2">
{CURRENCIES.map((c) => (
<Button
key={String(c)}
size="sm"
variant={currency === c ? 'primary' : 'outline'}
onClick={() => setCurrency(c)}
>
{c === false ? 'false' : c}
</Button>
))}
</div>
<dl className="divide-y divide-border rounded-xl border border-border bg-surface text-sm">
{rows.map((row) => (
<div key={row.call} className="flex flex-wrap justify-between gap-x-4 gap-y-1 px-3 py-2">
<dt className="font-mono text-xs text-text-muted">{row.call}</dt>
<dd className="font-mono font-medium text-text tabular-nums">{row.value || "''"}</dd>
</div>
))}
</dl>
</div>
);
}
formatNumber
function formatNumber(n: number, options?: FormatNumberOptions): string;Sonni minglik ajratuvchi bilan yozadi. Ajratuvchi — oddiy bo'sh joy (NBSP emas), shuning uchun
natijani nusxalab boshqa joyga qo'yish oson. NaN va Infinity → ''.
formatNumber(1250000); // '1 250 000'
formatNumber(1250000.756); // '1 250 000.756'
formatNumber(1250000.5, { decimals: 2 }); // '1 250 000.50'
formatNumber(1234567.891, { separator: ',', decimals: 2 }); // '1,234,567.89'
formatNumber(1234567.5, { decimalMark: ',', decimals: 1 }); // '1 234 567,5'
formatNumber(-4500); // '-4 500'
formatNumber(NaN); // ''| Prop | Tip | Standart | Tavsif |
|---|---|---|---|
decimals | number | — | Kasr qismidagi raqamlar (0–20). Berilmasa — son qanday bo'lsa, shunday |
separator | string | ' ' | Minglik ajratuvchi |
decimalMark | string | '.' | Kasr ajratuvchisi |
formatMoney
function formatMoney(n: number, options?: FormatMoneyOptions): string;Pul summasi. Standart holatda butun songa yaxlitlanadi va so'm qo'shiladi.
formatMoney(1250000); // "1 250 000 so'm"
formatMoney(1249999.6); // "1 250 000 so'm"
formatMoney(99.5, { currency: 'UZS', decimals: 2 }); // '99.50 UZS'
formatMoney(1250000, { currency: false }); // '1 250 000'
formatMoney(-99.5, { decimals: 2 }); // "-99.50 so'm"| Prop | Tip | Standart | Tavsif |
|---|---|---|---|
currency | "so'm" | 'UZS' | false | "so'm" | Valyuta belgisi; false — belgisiz |
decimals | number | 0 | Kasr qismidagi raqamlar |
separator | string | ' ' | Minglik ajratuvchi |
decimalMark | string | '.' | Kasr ajratuvchisi |
Kiritish maydoni kerakmi?
Foydalanuvchi summa yozadigan joyda MoneyInput ishlating — u
yozish paytida formatlaydi va toza son qaytaradi.
formatFileSize
function formatFileSize(bytes: number, decimals?: number): string;Fayl hajmini o'qiladigan ko'rinishga keltiradi: B, KB, MB, GB, TB (1 KB = 1024 B).
Ortiqcha nollar tashlanadi. Manfiy yoki noto'g'ri qiymat → ''.
formatFileSize(512); // '512 B'
formatFileSize(1024); // '1 KB'
formatFileSize(1536); // '1.5 KB'
formatFileSize(3565158); // '3.4 MB'
formatFileSize(3565158, 0); // '3 MB'
formatFileSize(-1); // ''decimals — kasr qismidagi raqamlar soni, standart 1.
Telefon va karta
Ikkala funksiya ham bosqichma-bosqich formatlaydi — to'liq bo'lmagan raqamni ham. Shuning
uchun ularni yozish paytida, onChange ichida chaqirish mumkin:
formatPhone: +998 90 123
Toza qiymat: 86001234
'use client';
import { formatCardNumber, formatPhone } from '@akhatmirzo/core';
import { Field, Input } from '@akhatmirzo/ui';
import { useState } from 'react';
const digitsOf = (s: string) => s.replace(/\D/g, '');
export default function CorePhoneCard() {
const [phone, setPhone] = useState('90123');
const [card, setCard] = useState('8600 1234');
return (
<div className="flex w-full max-w-sm flex-col gap-4">
<Field label="Telefon" description={`formatPhone: ${formatPhone(phone) || '—'}`}>
<Input
prefix="+998"
value={formatPhone(phone, 'national')}
onChange={(e) => setPhone(digitsOf(e.target.value).slice(0, 9))}
inputMode="tel"
placeholder="(90) 123-45-67"
/>
</Field>
<Field label="Karta raqami" description={`Toza qiymat: ${digitsOf(card) || '—'}`}>
<Input
value={card}
onChange={(e) => setCard(formatCardNumber(digitsOf(e.target.value).slice(0, 16)))}
inputMode="numeric"
placeholder="0000 0000 0000 0000"
/>
</Field>
</div>
);
}
formatPhone
function formatPhone(input: string | number | null | undefined, style?: PhoneStyle): string;
// PhoneStyle = 'international' | 'national'O'zbekiston raqamini formatlaydi. Bo'shliq, chiziqcha va qavslar e'tiborsiz qoldiriladi.
formatPhone('901234567'); // '+998 90 123 45 67'
formatPhone(901234567); // '+998 90 123 45 67'
formatPhone('+998 (90) 123-45-67'); // '+998 90 123 45 67'
formatPhone('+998901234567', 'national'); // '(90) 123-45-67'
formatPhone('90123', 'national'); // '(90) 123'
formatPhone(''); // ''998 prefiksi qachon olib tashlanadi
998 faqat + bilan yoki 9 tadan ko'p raqam berilganda davlat kodi deb hisoblanadi. Aks holda u
milliy raqamning boshi: formatPhone('998123456') → '+998 99 812 34 56' (operator 99).
formatCardNumber
function formatCardNumber(input: string | number | null | undefined): string;Karta raqamini 4 tadan guruhlaydi, ko'pi bilan 19 raqam.
formatCardNumber('8600123412341234'); // '8600 1234 1234 1234'
formatCardNumber('8600-1234-12'); // '8600 1234 12'Raqam to'g'riligini tekshirish uchun — isValidCardNumber.
Sana va vaqt
formatDate(sana, shablon) → 21 Oktabr 2026, Chorshanba
null — bunday sana yo'q
'use client';
import { formatDate, parseDate } from '@akhatmirzo/core';
import { Badge, Field, Input } from '@akhatmirzo/ui';
import { useState } from 'react';
const PATTERNS = ['dd.MM.yyyy', 'd MMMM yyyy, EEEE', 'd MMM, EEE', 'EEEE, d MMMM [soat] HH:mm'];
const DATE = new Date(2026, 9, 21, 14, 30);
export default function CoreDate() {
const [pattern, setPattern] = useState('d MMMM yyyy, EEEE');
const [input, setInput] = useState('31.02.2026');
const parsed = parseDate(input);
return (
<div className="flex w-full max-w-md flex-col gap-4">
<Field
label="Shablon"
description={`formatDate(sana, shablon) → ${formatDate(DATE, pattern)}`}
>
<Input value={pattern} onChange={(e) => setPattern(e.target.value)} />
</Field>
<div className="flex flex-wrap gap-2">
{PATTERNS.map((p) => (
<button key={p} type="button" onClick={() => setPattern(p)} className="cursor-pointer">
<Badge variant="outline">{p}</Badge>
</button>
))}
</div>
<Field
label="parseDate (dd.MM.yyyy)"
description={parsed ? formatDate(parsed, 'EEEE, d MMMM yyyy') : "null — bunday sana yo'q"}
>
<Input value={input} onChange={(e) => setInput(e.target.value)} invalid={!parsed} />
</Field>
</div>
);
}
formatDate
function formatDate(date: DateInput, pattern?: string): string;
// DateInput = Date | number | string | null | undefinedSanani shablon bo'yicha formatlaydi (mahalliy vaqtda). Oy va hafta kunlari o'zbekcha. Standart
shablon — 'dd.MM.yyyy'. Noto'g'ri sana → ''.
const date = new Date(2026, 9, 21, 14, 5);
formatDate(date); // '21.10.2026'
formatDate(date, 'd MMMM yyyy, EEEE'); // '21 Oktabr 2026, Chorshanba'
formatDate(date, 'd MMM, EEE'); // '21 Okt, Ch'
formatDate(date, 'yyyy-MM-dd HH:mm'); // '2026-10-21 14:05'
formatDate(date, 'EEEE, d MMMM [soat] HH:mm'); // 'Chorshanba, 21 Oktabr soat 14:05'
formatDate('sana emas'); // ''Jadvaldagi natijalar new Date(2026, 2, 5, 9, 5, 7) — 5-mart 2026, 09:05:07 uchun:
| Token | Natija | Token | Natija |
|---|---|---|---|
yyyy / yy | 2026 / 26 | HH / H | 09 / 9 (soat) |
MMMM | Mart | mm / m | 05 / 5 (daqiqa) |
MMM | Mar | ss / s | 07 / 7 (soniya) |
MM / M | 03 / 3 | EEEE | Payshanba |
dd / d | 05 / 5 | EEE | Pa |
Kvadrat qavs ichidagi matn o'zgarmaydi: '[soat] HH:mm' → 'soat 14:05'.
parseDate
function parseDate(input: string | null | undefined, pattern?: string): Date | null;Matnni shu shablonlar bo'yicha sanaga aylantiradi (mahalliy vaqt). Shablonga mos kelmasa yoki
bunday sana mavjud bo'lmasa — null. Oy nomlari katta-kichik harfga sezgir emas, yy → 20yy,
chetdagi bo'shliqlar e'tiborsiz.
parseDate('21.10.2026'); // Date: 21-oktabr 2026, 00:00
parseDate('31.02.2026'); // null — 31-fevral yo'q
parseDate('5 oktabr 2026', 'd MMMM yyyy'); // Date: 5-oktabr 2026
parseDate('2026-10-21 14:30', 'yyyy-MM-dd HH:mm'); // Date: 21-oktabr 2026, 14:30
parseDate('21.10.26', 'dd.MM.yy'); // Date: 21-oktabr 2026timeAgo
function timeAgo(date: DateInput, now?: DateInput): string;Nisbiy vaqt: o'tmish uchun "… oldin", kelajak uchun "…dan keyin". Bir daqiqadan kam farq —
"hozirgina", bir sutkagacha — daqiqa yoki soat. Sutkadan ko'p farqda kunlar kalendar bo'yicha
sanaladi: 19-oktabr 23:00 21-oktabr ertalab 08:00 dan qaraganda (33 soat) "2 kun oldin" bo'ladi.
now — taqqoslash nuqtasi, standart new Date().
timeAgo → 1 soat oldin
- 5 daqiqa5 daqiqa oldin
- 180 daqiqa3 soat oldin
- 1440 daqiqakecha
- 4320 daqiqa3 kun oldin
- 20160 daqiqa2 hafta oldin
- 136800 daqiqa3 oy oldin
- -120 daqiqa2 soatdan keyin
- -1440 daqiqaertaga
'use client';
import { timeAgo } from '@akhatmirzo/core';
import { Field, Input } from '@akhatmirzo/ui';
import { useState } from 'react';
const MINUTE = 60_000;
const NOW = new Date(2026, 9, 21, 12, 0);
const OFFSETS = [5, 180, 1440, 4320, 20160, 136800, -120, -1440];
export default function CoreTimeAgo() {
const [minutes, setMinutes] = useState('90');
const custom = new Date(NOW.getTime() - Number(minutes || 0) * MINUTE);
return (
<div className="flex w-full max-w-sm flex-col gap-4">
<Field label="Necha daqiqa oldin" description={`timeAgo → ${timeAgo(custom, NOW)}`}>
<Input
value={minutes}
onChange={(e) => setMinutes(e.target.value.replace(/[^\d-]/g, ''))}
inputMode="numeric"
suffix="daqiqa"
/>
</Field>
<ul className="divide-y divide-border rounded-xl border border-border bg-surface text-sm">
{OFFSETS.map((m) => (
<li key={m} className="flex justify-between gap-4 px-3 py-2">
<span className="font-mono text-xs text-text-muted">{m} daqiqa</span>
<span className="text-text">{timeAgo(NOW.getTime() - m * MINUTE, NOW)}</span>
</li>
))}
</ul>
</div>
);
}
const now = new Date(2026, 9, 21, 12, 0);
const minutes = (m: number) => new Date(now.getTime() - m * 60_000);
timeAgo(minutes(0.5), now); // 'hozirgina'
timeAgo(minutes(5), now); // '5 daqiqa oldin'
timeAgo(minutes(180), now); // '3 soat oldin'
timeAgo(minutes(1440), now); // 'kecha'
timeAgo(minutes(4320), now); // '3 kun oldin'
timeAgo(minutes(20160), now); // '2 hafta oldin'
timeAgo(minutes(-120), now); // '2 soatdan keyin'
timeAgo(minutes(-1440), now); // 'ertaga'Birliklar: daqiqa, soat, kun, hafta, oy va yil.
Oy va hafta kunlari
const MONTHS_UZ: readonly ['Yanvar', 'Fevral', …, 'Dekabr'];
const MONTHS_UZ_SHORT: readonly ['Yan', 'Fev', 'Mar', 'Apr', 'May', 'Iyn', 'Iyl', …];
const WEEKDAYS_UZ: readonly ['Dushanba', 'Seshanba', …, 'Yakshanba'];
const WEEKDAYS_UZ_SHORT: readonly ['Du', 'Se', 'Ch', 'Pa', 'Ju', 'Sh', 'Ya'];
function weekdayIndex(date: Date): number; // 0 = Dushanba … 6 = YakshanbaHafta dushanbadan boshlanadi. JavaScript'ning getDay() esa yakshanbadan sanaydi, shuning
uchun indeksni weekdayIndex bilan oling:
WEEKDAYS_UZ[weekdayIndex(new Date(2026, 9, 21))]; // 'Chorshanba'
weekdayIndex(new Date(2026, 9, 25)); // 6 — yakshanbaQisqa oy nomlarida Iyun va Iyul Iyn / Iyl — bir-biridan farqlanishi uchun.