قالب‌بندی زمان

زمان در یک رابط کاربری به سه شکل گوناگون ظاهر می‌شود، و درهم آمیختن آن‌ها سرچشمهٔ همیشگی سردرگمی است. ranuts برای هر کدام تابعی جداگانه دارد:

پرسشی که خواننده دارد تابع نمونهٔ خروجی
این دقیقاً کِی رخ داده است؟ formatDate 2026-07-25 14:05:09
این چقدر طول می‌کشد؟ formatDuration 01:01:01
چند وقت پیش بوده است؟ formatRelative 3 days ago، 5m

formatDuration

شمار ثانیه‌های سپری‌شده را به شکل ساعتِ جداشده با دونقطه درمی‌آورد؛ همان شکلی که یک پخش‌کننده برای نشانگر پخش به کار می‌برد: mm:ss که از یک ساعت که بگذرد به hh:mm:ss گشوده می‌شود.

پارامترها

پارامتر توضیح نوع پیش‌فرض
seconds ثانیه‌های سپری‌شده؛ مقدارهای منفی به ۰ چسبانده می‌شوند number الزامی

Returns

string: خودِ مدت، یا '' اگر ورودی عددی متناهی نباشد.

import { formatDuration } from 'ranuts/utils';

formatDuration(0); // '00:00'
formatDuration(65); // '01:05'
formatDuration(3661); // '01:01:01'
formatDuration(NaN); // ''

بازگرداندن رشتهٔ تهی در برابر NaN عمدی است: پخش‌کننده پیش از بارگیری فراداده سراغ video.duration می‌رود و NaN می‌گیرد، و آنجا یک برچسب خالی بهتر از NaN:NaN خوانده می‌شود.

formatRelative

یک لحظه را نسبت به لحظه‌ای دیگر توصیف می‌کند: «۳ روز پیش»، «۲ ساعت دیگر».

بومی‌سازی به Intl.RelativeTimeFormat خودِ بستر سپرده می‌شود که از ۲۰۲۰ در همهٔ مرورگرهای مهم هست و قاعده‌های جمع و صرف هر زبان را از پیش می‌داند. formatRelative تنها همان بخشی را می‌آورد که Intl عمداً کنار گذاشته است: اینکه فاصله را با کدام یکا بیان کنیم.

مانند خودِ Intl تنها یک یکا گزارش می‌کند: فاصلهٔ ۳ روز و ۶ ساعت می‌شود «۳ روز پیش»، و هرگز «۳ روز و ۶ ساعت پیش» نمی‌شود.

پارامترها

پارامتر توضیح نوع پیش‌فرض
value لحظه‌ای که می‌خواهی توصیف شود number | string | Date الزامی
options پایین‌تر ببین FormatRelativeOptions {}
گزینه توضیح نوع پیش‌فرض
now آنچه فاصله نسبت به آن سنجیده می‌شود number | string | Date زمان کنونی
locale برچسب یا برچسب‌های BCP 47؛ سبک compact نادیده‌شان می‌گیرد string | string[] زبان محیط اجرا
style 'long' | 'short' | 'narrow' | 'compact' RelativeStyle 'long'
numeric با 'auto' تعبیرهایی مانند yesterday جایگزین می‌شوند؛ با 'always' عددها سر جایشان می‌مانند 'always' | 'auto' 'auto'

Returns

string — همان توصیف، یا '' هرگاه یکی از دو سر قابل خواندن نباشد.

import { formatRelative } from 'ranuts/utils';

const twoHoursAgo = Date.now() - 2 * 3600_000;

formatRelative(twoHoursAgo); // '2 hours ago'
formatRelative(twoHoursAgo, { style: 'short' }); // '2 hr. ago'
formatRelative(twoHoursAgo, { locale: 'zh-CN' }); // '2 小时前'
formatRelative(Date.now() + 60_000); // 'in 1 minute'
formatRelative(Date.now() - 86_400_000); // 'yesterday'
formatRelative(Date.now() - 86_400_000, { numeric: 'always' }); // '1 day ago'

سبک compact

compact همان شکل فشردهٔ نشان‌گونه است که کنار آیتم‌های یک خوراک یا فهرست دیده می‌شود:

formatRelative(Date.now() - 30_000, { style: 'compact' }); // '30s'
formatRelative(Date.now() - 5 * 60_000, { style: 'compact' }); // '5m'
formatRelative(Date.now() - 3 * 3600_000, { style: 'compact' }); // '3h'
formatRelative(Date.now() - 2 * 86_400_000, { style: 'compact' }); // '2d'

parseVttTimestamp / parseVttCueTiming

خواندن زمان‌بندی زیرنویس WebVTT: همان خط‌های hh:mm:ss.mmm --> hh:mm:ss.mmm در یک فایل .vtt.

parseVttTimestamp یک مهر زمانی را (که hh: در آن اختیاری است) به ثانیه تبدیل می‌کند؛ parseVttCueTiming یک خط زمان‌بندی کامل را می‌خواند، یعنی هر دو سوی جداشده با --> را به { start, end } تبدیل می‌کند و تنظیم‌های نشانه‌ای که در انتها بیایند (align:start line:0) را نادیده می‌گیرد.

import { parseVttTimestamp, parseVttCueTiming } from 'ranuts/utils';

parseVttTimestamp('00:00:05.000'); // 5
parseVttTimestamp('01:05.250'); // 65.25
parseVttTimestamp('not a timestamp'); // undefined

parseVttCueTiming('00:00:00.000 --> 00:00:05.000'); // { start: 0, end: 5 }
parseVttCueTiming('00:00:05.000 --> 00:00:10.000 align:start line:0'); // { start: 5, end: 10 }

هر دو وقتی ورودی جور درنیاید undefined برمی‌گردانند و هرگز خطا نمی‌اندازند، پس یک خط بدشکل در فایل زیرنویس را می‌توان رد کرد به‌جای آنکه کل خواندن از هم بپاشد.

یادداشت‌ها

  1. گزینش یکا: formatRelative درشت‌ترین یکایی را برمی‌دارد که فاصله واقعاً آن را پر می‌کند و سپس درون همان گرد می‌کند. هرگاه گرد کردن روی آستانهٔ یکای بعدی بنشیند (۵۹٫۶ دقیقه که به «۶۰ دقیقه» گرد می‌شود)، یک پله بالا می‌رود تا «۱ ساعت پیش» خوانده شود.
  2. گرد کردن متقارن: اندازه گرد می‌شود و سپس علامت دوباره بر آن نهاده می‌شود، چون در جاوااسکریپت Math.round(-1.5) برابر -1 است و در غیر این صورت ۹۰ دقیقه پیش «۱ ساعت پیش» خوانده می‌شد حال آنکه ۹۰ دقیقه بعد «۲ ساعت دیگر» می‌شد.
  3. استفادهٔ دوباره از قالب‌بند: نمونه‌های Intl.RelativeTimeFormat برای هر ترکیب زبان، سبک و numeric در حافظهٔ نهان نگه داشته می‌شوند، پس فهرستی که صد مهر زمانی را می‌کشد یک قالب‌بند می‌سازد، نه صد تا.
  4. راه جایگزین: در محیط اجرایی که Intl.RelativeTimeFormat ندارد، خروجی به‌جای خطا انداختن به شکل فشرده بازمی‌گردد.