前端進階
-如何轉換網頁中的貨幣單位、日期格式?- JS Intl 詳解
你知道 JS Intl 這很有意思的 API 嗎?
他提供許多方法來處理不同地區和語言的文法、日期、貨幣格式,讓你在解決網站需要國際化時可能會遇到的格式問題。
我們可以直接在控制台裡輸入 Intl,可以發現有許多物件和方法👇
今天我會挑五個實用的來介紹,分別為
- Intl.Collator 依照語言特性做排序
- Intl.DateTimeFormat 轉化時間格式
- Intl.NumberFormat 轉化貨幣格式
Intl.Collator 依照語言特性做排序
Intl.Collator
用來比較和排序字串,他接受兩個參數,像下面這樣:
const intl = new Intl.Collator(locales, { options })
- locales: 這個參數可以指定用哪個語言的語法來排序,是根據 BCP 47 來決定的,比如台灣是 zh-TW
- options: 可選參數,用來調整一些在比較時的設定
Collator
可以根據當地語言的特性來排序,比如我們在使用 sort()
做排序的時候,可能會因為中文的關係出現意料之外的排法,此時我們就可以用 Intl.Collator
解決,像是我們可以用注音來排序:
const names = ['李四', '王二', '張三', '陳一']
const collator = new Intl.Collator('zh-TW', {
collation: 'zhuyin',
});
names.sort(collator.compare);
// ['李四', '張三', '陳一', '王二']
其中 collation 有多種值可以選擇,跟中文有關的有
- zhuyin: 依照注音排序
- stroke: 依照筆畫排序
- pinyin: 依照漢語拼音做排序
而 collator.compare
是對傳入的兩個參數做比較,所以可以搭配陣列的 sort()
做使用:
new Intl.Collator().compare("a", "c"); // -1
new Intl.Collator().compare("c", "a"); // 1
除了依照注音排序,也可以像這樣對中文的數字做排序:
const numbers = ['五', '三', '四', '一', '二']
const collator = new Intl.Collator('zh-TW', {
numeric: true,
});
numbers.sort(collator.compare);
['一', '二', '三', '五', '四']
Intl.DataTimeFormat 轉換日期和時間格式
他用來根據不同的語言,轉換不同的日期或時間格式,Intl 系列基本上都包含兩個參數,差別在於第二個參數可以傳入的屬性,會根據使用 Intl 方法而有所不同
使用方法如下:
const date = new Date();
const options = {
dateStyle: 'full',
timeStyle: 'medium',
hour12: true,
timeZone: 'Asia/Taipei',
};
const formatter = new Intl.DateTimeFormat('zh-TW', options);
const formattedDate = formatter.format(date);
console.log(formattedDate);
// 2023年4月28日 星期五 晚上9:56:08
- dateStyle: 決定日期的表示方式
- full: 2023年4月28日 星期五
- long: 2023年4月28日
- medium: 2023年4月28日,在中文裡和 long 一樣
- short
- timeStyle: 決定時間 (時 / 分 / 秒) 的表示方式
- full
- long
- medium
- short
- hour12: 時間是 12 小時還是 24 小時制
- true: 12小時
- false: 24 小時
- timeZone: 時區
也可以客製化年月日
const date = new Date();
const options = {
year: '2-digit',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false,
timeZone: 'Asia/Taipei',
};
const formatter = new Intl.DateTimeFormat('zh-TW', options);
const formattedDate = formatter.format(date);
console.log(formattedDate); // 23/04/28 22:02:49
其中 2-digit
表示一定使用 2 位數字表示,若數字沒超過 10,會在前面補 0
還有非常多的屬性可以調整,有需要再去看就好。
Intl.ListFormat 將陣列格式轉換成口語文法
Intl.ListFormat
用來將多個元素的陣列格式轉換成我們常用的文法,例如
const fruits = ['蘋果', '香蕉', '橘子', '芒果'];
const options = { style: 'long', type: 'conjunction' };
const formatter = new Intl.ListFormat('zh-TW', options);
const formattedList = formatter.format(fruits);
console.log(formattedList); // "蘋果、香蕉、橘子和芒果"
是一個蠻特別的用法,在某些場景可以很快速將陣列直接轉換成我們字串,而且更口語化。
Intl.NumberFormat 轉換數字成特定語言用法
Intl.NumberFormat 用來格式轉換數字,轉換成特定語言的用法,例如增加逗號,也可以增加貨幣符號
const formatter = new Intl.NumberFormat('zh-TW', {
style: 'currency',
currency: 'TWD',
currencyDisplay: 'name'
});
const price = 1234.56;
console.log(formatter.format(price)); // 1,234.56 新台幣
- style: 數字格式轉換使用的樣式
- decimal: 純數字
- currency: 可以指定 currency 屬性來增加貨幣單位
- percent: 百分比
- currency: 指定貨幣的單位,參考 ISO 4217 的貨幣代碼 (可以上維基看每個國家的貨幣代碼,例如台灣是 TWD,美金是 USD)
- currencyDisplay: 貨幣單位的表示方式
- symbol: 用符號表式
- code: 用 ISO 4217 貨幣代碼表示
- name: 用語言表示
這個方法蠻特別的,他還可以做些數字上的操作,例如千分數字或前面補 0,甚至是數字轉中文
new Intl.NumberFormat().format(12345.6789);
// 12,345.6789
new Intl.NumberFormat('en-US', {
minimumIntegerDigits: 2
}).format(8); // 08
new Intl.NumberFormat('en-US', {
style: 'percent',
minimumFractionDigits: 2,
}).format(0.75); // 75.00%
new Intl.NumberFormat('zh-Hans-TW-u-nu-hanidec')
.format(123456) // 一二三,四五六
Intl.RelativeTimeFormat 表示相對時間
Intl.RelativeTimeForma
t 是用來表示相對時間的,比如5分鐘前或3個月後,這在部落格表示文章時間時超級實用。
const formatter = new Intl.RelativeTimeFormat('zh-TW', {numeric: 'auto'});
console.log(formatter.format(-3, 'day')); // 3 天前
console.log(formatter.format(-1, 'day')); // 昨天
console.log(formatter.format(2, 'day')); // 明天過後 不對,是 後天
console.log(formatter.format(1, 'hour')); // 1 小時候
- numeric: 表示相對時間的方式
- always: 永遠用數字表示,比如昨天會變 1 天前
- auto: 自動使用語言常用的方式
不過可惜的是,他並不支持直接傳日期進去計算時間差,只能額外計算。
const createRelativeTimeString = (dateString) => {
const now = new Date();
const postDate = new Date(dateString);
const timeDiff = now.getTime() - postDate.getTime();
const daysDiff = Math.floor(timeDiff / (1000 * 3600 * 24));
const hoursDiff = Math.floor(timeDiff / (1000 * 3600));
if (daysDiff > 7) {
// 超過一個禮拜,用日期表示
const formatter = new Intl.DateTimeFormat('zh-TW');
return formatter.format(postDate);
} else if (daysDiff > 0) {
// 一個禮拜以內,用幾天前表示
const rtf = new Intl.RelativeTimeFormat('zh-TW');
return rtf.format(-daysDiff, 'day');
} else {
// 一天內,用小時表示
const rtf = new Intl.RelativeTimeFormat('zh-TW');
return rtf.format(-hoursDiff, 'hour');
}
};
// 假設今天是 2023/4/28
console.log(createRelativeTimeString('2023-04-25T12:00:00Z')); // 3 天前
console.log(createRelativeTimeString('2023-04-28T09:00:00Z')); // 5 小時前
console.log(createRelativeTimeString('2023-04-20T12:00:00Z')); // 2023/4/20
小結
今天介紹了 5 個好用的 JS Intl API,在網站要做國際化的時候非常好用!
JS Intl 還有其他用法,不過有些都不太常用,有需要再去看看就好,這篇就這樣,希望能幫你快速了解這個 API 在幹嘛,下次見~!