format
Functions that format dates and times for the app's language, plus defineStrings for defining per-language string tables.
This module helps you show text in the app's current language. It does two things: it defines a plugin's Chinese and English string tables, and it formats dates, times and countdowns the way each language writes them.
Source: packages/sdk/src/format.ts. Guide: Languages. The locale
parameter below has the type AppLocale, which is 'zh-Hans' | 'en'.
The app runs on Hermes, the JavaScript engine of React Native. Hermes' Intl ignores the locale
argument, so these helpers don't use Intl and build the strings themselves. Their output matches
the app's own date formatting, which keeps plugin screens consistent with the rest of the app. All
of them are pure functions. In tests, pass the now argument to get fixed results.
String tables
A string table keeps the Chinese and English versions of the same text together. defineStrings
type-checks the English version against the Chinese one: a missing or extra key, or a value of a
different type, is a compile error.
/** Per-locale string table; `en` must have exactly the keys (and value types) of `zh-Hans`. */
type Localized<T> = { 'zh-Hans': T; en: T };
/** Define a plugin's string table with `en` type-checked against `zh-Hans`. */
const defineStrings: <T>(table: { 'zh-Hans': T; en: NoInfer<T> }) => Localized<T>;Dates and times
The table lists the signature of each formatting function and sample output in both languages.
| Function | Signature | zh-Hans | en |
|---|---|---|---|
formatClock | (d: Date | number, seconds?: boolean) => string | 21:04 / 21:04:37 | same |
formatWeekday | (d: Date | number, locale) => string | 周一 | Mon |
weekdayName | (weekday: number, locale) => string (1 = Monday … 7 = Sunday; 0 also means Sunday) | 周一 | Mon |
formatLocalDate | (d, locale, now?) => string (adds the year when it isn't the current one) | 10月18日, 2025年10月18日 | Oct 18, Oct 18, 2025 |
formatLocalDateTime | (d, locale, now?) => string | 10月18日 21:04 | Oct 18, 21:04 |
formatRelative | (ms: number, locale, now?) => string (past timestamps) | 刚刚, 3 分钟前, 21:04, 昨天 21:04, then date + time | Just now, 3 min ago, 21:04, Yesterday 21:04, … |
formatDay | (d, locale, now?) => string | 今天, 明天, 昨天, 周三 (within the coming week), date | Today, Tomorrow, Yesterday, Wed, date |
formatCountdown | (ms: number, locale) => string (time left) | 3天5小时, 2小时10分, 8分钟, 不到1分钟, 已到 | 3d 5h, 2h 10m, 8 min, <1 min, Now |
dayDiff | (d, now?) => number | calendar days from now (0 today, 1 tomorrow, −1 yesterday), DST-safe | |
plural | (n: number, one: string, many?: string) => string | — | plural(3, 'book') → 3 books |
import { formatCountdown, formatRelative } from '@pku-harness/sdk';
const locale = host.useLocale();
formatRelative(data.updatedAt ?? Date.now(), locale); // "3 分钟前" / "3 min ago"
formatCountdown(deadline - Date.now(), locale); // "2小时10分" / "2h 10m"These functions are for text the user sees. Timestamps for the model are handled separately. The
host adds the current time to every chat turn, and the schedule tools use formatLocal from
scheduler, which prints strings like "2026-10-20 08:00 周二".