國際化相對時間格式化API:Intl.RelativeTimeFormat
現代 Web 應用程式通常使用“昨天”,“42秒前”或“3個月”之類的短語,而不是完整的日期和時間戳。這種相對時間格式已經變得非常普遍,以至於幾個流行的庫都實現了本地化格式化的函式。(例如Moment.js,ofollow,noindex">Globalize 和date-fns。)
實現本地化相對時間格式化的一個問題是,您需要為每種語言提供習慣詞或短語列表(例如“昨天”或“上一季度”)。Unicode CLDR 提供了此資料,但要在 JavaScript 中使用它,必須將其嵌入到庫程式碼中一起提供。遺憾的是,這無疑會增加這些庫的包大小,這會影響到指令碼的載入時間、解析/編譯成本和記憶體消耗。
全新的Intl.RelativeTimeFormat
API 將此負擔轉移到了 JavaScript 引擎,JavaScript 引擎可以提供語言環境資料並使其直接供 JavaScript 開發人員使用。Intl.RelativeTimeFormat
在不犧牲效能的情況下實現相對時間的本地化格式化。
用法與示例
以下示例展示瞭如何使用英語建立相對時間格式化程式。
const rtf = new Intl.RelativeTimeFormat('en'); rtf.format(3.14, 'second'); // → 'in 3.14 seconds' rtf.format(-15, 'minute'); // → '15 minutes ago' rtf.format(8, 'hour'); // → 'in 8 hours' rtf.format(-2, 'day'); // → '2 days ago' rtf.format(3, 'week'); // → 'in 3 weeks' rtf.format(-5, 'month'); // → '5 months ago' rtf.format(2, 'quarter'); // → 'in 2 quarters' rtf.format(-42, 'year'); // → '42 years ago' 複製程式碼
需要注意的是傳遞給Intl.RelativeTimeFormat
建構函式的引數必須是一個 BCP 47 語言標記,或者是一個包括多個語言標記的陣列
。
以下是使用其他語言(漢語簡體中文)的示例:(譯註:原文是西班牙語)
const rtf = new Intl.RelativeTimeFormat('zh'); // 或 'zh-Hans-CN' rtf.format(3.14, 'second'); // → '3.14秒鐘後' rtf.format(-15, 'minute'); // → '15分鐘前' rtf.format(8, 'hour'); // → '8小時後' rtf.format(-2, 'day'); // → '2天前' rtf.format(3, 'week'); // → '3周後' rtf.format(-5, 'month'); // → '5個月前' rtf.format(2, 'quarter'); // → '2個季度後' rtf.format(-42, 'year'); // → '42年前' 複製程式碼
此外,Intl.RelativeTimeFormat
建構函式還接受一個可選options
引數,該引數可以對輸出進行細粒度控制。為了說明靈活性,讓我們根據預設設定檢視更多輸出:
// 建立一個簡體中文相對時間格式化示例,使用預設設定。 // 在這個例子中,我們將預設引數顯式的傳進去 const rtf = new Intl.RelativeTimeFormat('zh', { localeMatcher: 'best fit', // 其他值: 'lookup' style: 'long', // 其他值: 'short' 或 'narrow' numeric: 'always', // 其他值: 'auto' }); rtf.format(-1, 'day'); // → '1天前' rtf.format(0, 'day'); // → '0天后' rtf.format(1, 'day'); // → '1天后' rtf.format(-1, 'week'); // → '1周前' rtf.format(0, 'week'); // → '0周後' rtf.format(1, 'week'); // → '1周後' 複製程式碼
您可能已經注意到上面的格式化程式生成了字串'1天前'
而不是'昨天'
,還有顯得比較弱智的'0周後'
而不是'本週'
。發生這種情況是因為預設情況下,格式化程式使用數值進行輸出。
要更改此行為,請將numeric
選項設定為'auto'
(預設值是'always'
):
const rtf = new Intl.RelativeTimeFormat('zh', { numeric: 'auto' }); rtf.format(-1, 'day'); // → '昨天' rtf.format(-2, 'day'); // → '前天' rtf.format(0, 'day'); // → '今天' rtf.format(1, 'day'); // → '明天' rtf.format(2, 'day'); // → '後天' rtf.format(-1, 'week'); // → '上週' rtf.format(0, 'week'); // → '本週' rtf.format(1, 'week'); // → '下週' 複製程式碼
Analogous to otherIntl
classes,Intl.RelativeTimeFormat
has aformatToParts
method in addition to the format method. Although format covers the most common use case,formatToParts
can be helpful if you need access to the individual parts of the generated output:
與其他Intl
類一樣,Intl.RelativeTimeFormat
除了format
方法之外,還有一個formatToParts
方法。雖然format
涵蓋了最常見的用例,但如果您需要訪問生成的輸出的各個部分,formatToParts
會很有幫助:
const rtf = new Intl.RelativeTimeFormat('zh', { numeric: 'auto' }); rtf.format(-1, 'day'); // → '昨天' rtf.formatToParts(-1, 'day'); // → [{ type: 'literal', value: '昨天' }] rtf.format(3, 'week'); // → '3周後' rtf.formatToParts(3, 'week'); // → [ //{ type: 'integer', value: '3', unit: 'week' }, //{ type: 'literal', value: '周後' } // ] 複製程式碼
有關其餘選項及其行為的詳細資訊,請參閱API docs in the proposal repository .