背景
因为我们开发的项目在多个国家和地区使用,不同国家和地区对于日期的显示习惯是不同的。例如:我们习惯使用 年-月-日 的方式显示日期,而英国习惯使用 日-月-年 的方式显示日期。因此在这里介绍一下日期本地化函数 toLocaleString。
简介
toLocaleString() 方法返回日期对象的字符串,该字符串因语言环境、配置的选项不同而不同。新增的参数 locales 和 options 使程序能够指定语言环境、选项。在旧版浏览器中, locales 和 options 参数被忽略。
let event = new Date(Date.UTC(2012, 11, 20, 3, 0, 0));
// 英国使用 日-月-年 的顺序,24小时制,不带 AM/PM
event.toLocaleString('en-GB', { timeZone: 'UTC' }); // 20/12/2012, 03:00:00
// 韩国使用 年-月-日 的顺序,12小时制 + AM/PM
event.toLocaleString('ko-KR', { timeZone: 'UTC' }); // 2012. 12. 20. 오전 3:00:00
语法
dateObj.toLocaleString([locales [, options]])
查看 浏览器兼容性,看下哪些浏览器支持 locales 和 options 参数,还可以参看 例子:检测 locales 和 options 参数支持情况。
参数
-
locales:
可选,值是遵循 BCP47 规范的语言标记字符串或此类字符串数组,如果想使用浏览器默认的语言环境,忽略这个参数或者传 undefined 即可。
支持 Unicode 扩展。例如:'en-US-u-ca-buddhist',其中 'en-US' 是 BCP47 语言标记,表示美国使用的英语;'u' 代表 Unicode,表示其后是 Unicode 扩展;'ca' 代表 Calendar,'buddhist' 是 ca 的值。允许使用以下 Unicode 扩展密钥:
-
nu
Numbering system. Possible values include:
'arab','arabext','bali','beng','deva','fullwide','gujr','guru','hanidec','khmr','knda','laoo','latn','limb','mlym','mong','mymr','orya','tamldec','telu','thai','tibt' -
ca
Calendar. Possible values include:
'buddhist','chinese','coptic','ethiopia','ethiopic','gregory','hebrew','indian','islamic','islamic','iso8601','japanese','persian','roc'. -
hc
Hour cycle. Possible values include:
'h11','h12','h23','h24'.
const event = new Date(Date.UTC(2012, 11, 20, 3, 0, 0)); event.toLocaleString('en-US', { timeZone: 'UTC' }); // '12/20/2012, 3:00:00 AM' event.toLocaleString('en-US-u-ca-buddhist', { timeZone: 'UTC' }); // '12/20/2555, 3:00:00 AM'更多信息请参考 Intl page。
-
-
options: 可选,对象,有以下属性:
-
dateStyle:可选值:
'full', 'long', 'medium', 'short'。const event = new Date(Date.UTC(2012, 11, 20, 3, 0, 0)); event.toLocaleString('en-GB', { timeZone: 'UTC' }); // '20/12/2012, 03:00:00' event.toLocaleString('en-GB', { timeZone: 'UTC', dateStyle: 'full' }); // 'Thursday, 20 December 2012' event.toLocaleString('en-GB', { timeZone: 'UTC', dateStyle: 'long' }); // '20 December 2012' event.toLocaleString('en-GB', { timeZone: 'UTC', dateStyle: 'medium' }); // '20 Dec 2012' event.toLocaleString('en-GB', { timeZone: 'UTC', dateStyle: 'short' }); // '20/12/2012' -
timeStyle:可选值:
'full', 'long', 'medium', 'short'。const event = new Date(Date.UTC(2012, 11, 20, 3, 0, 0)); event.toLocaleString('en-GB', { timeZone: 'UTC' }); // '20/12/2012, 03:00:00' event.toLocaleString('en-GB', { timeZone: 'UTC', timeStyle: 'full' }); // '03:00:00 Coordinated Universal Time' event.toLocaleString('en-GB', { timeZone: 'UTC', timeStyle: 'long' }); // '03:00:00 UTC' event.toLocaleString('en-GB', { timeZone: 'UTC', timeStyle: 'medium' }); // '03:00:00' event.toLocaleString('en-GB', { timeZone: 'UTC', timeStyle: 'short' }); // '03:00' -
localeMatcher:locale 匹配策略;可选值是:
'lookup', 'best fit';默认值是'best fit'。更多信息请参考 Intl page. -
timeZone: 指定时区;可选值是:'UTC';默认值是当前浏览器的默认时区。浏览器也能识别出 IANA 时区数据库 的时区名称,例如:'Asia/Shanghai', 'Asia Kolkata', 'America/New_York'。
-
hour12: 是否使用12小时制时间(对应的是 24小时制);可选值:
true, false。默认值和locale有关,它比 locales 中 Unicode 扩展标记中的hc和hourCycle优先级都高。 -
hourCycle: 要使用的小时循环。可选值:
'h11', 'h12', 'h23', 'h24'。它比 locales 中 Unicode 扩展标记中的hc优先级高,比hour12优先级低。 -
formatMatcher: 格式化匹配策略;可选值是
'lookup', 'best fit';默认值是'best fit'。 -
weekday:星期的表示,可选值如下:
- 'long' (e.g. Thursday)
- 'short' (e.g. Thu)
- 'narrow' (e.g. T) 注意一些地区的简写可能是相同的,比如:Thursday & Thursday。
-
era:时代的表示,可选值如下:
- 'long' (e.g. Anno Domini) 公元
- 'short' (e.g. AD)
- 'narrow' (e.g. A)
-
year:年的表示,可选值如下:
- 'numeric' (e.g. 2012)
- '2-digit' (e.g. 12)
-
month:月的表示,可选值如下:
- 'numeric' (e.g. 2)
- '2-digit' (e.g. 02)
- 'long' (e.g. March)
- 'short' (e.g. Mar)
- 'narrow' (e.g. M) 注意一些地区的月的 'narrow' 简写可能是相同的,比如:March & May。
-
day:日的表示,可选值如下:
- 'numeric' (e.g. 1)
- '2-digit' (e.g. 01)
-
hour:小时的表示,可选值是:'numeric' & '2-digit'
-
minute:分钟的表示,可选值是:'numeric' & '2-digit'
-
second:秒的表示,可选值是:'numeric' & '2-digit'
-
timeZoneName:时区名的表示,可选值如下:
- 'long' (e.g. British Summer Time)
- 'short' (e.g. GMT+1)
-
Demos
不带参数
没有指定语言环境(locales)时,返回一个使用默认语言环境和格式设置(options)的格式化字符串。
// toLocaleString 不包含参数的返回值取决于当前浏览器的默认语言环境(locales)和默认时区(time zone),我机器的语言环境是简体中文(cn-ZH),时区是东八区
const event = new Date(Date.UTC(2012, 11, 20, 3, 0, 0));
event.toLocaleString(); // '2012/12/20 上午11:00:00'
// 如果是在 en-US 语言环境和 America/Los_Angeles 时区运行返回值为 '12/19/2012, 7:00:00 PM'
event.toLocaleString('en-US', { timeZone: 'America/Los_Angeles' }); // '12/19/2012, 7:00:00 PM'
locales 和 options 参数不是所有的浏览器都支持。为了检测浏览器是否支持它们,可以使用不合法的语言标签,如果实现环境支持该参数,则会抛出一个 RangeError 异常,反之会忽略参数。
function toLocaleStringSupportsLocales() {
try {
new Date().toLocaleString('i');
} catch (e) {
return e.name === 'RangeError';
}
return false;
}
使用 locales 参数
下例展示了使用 locales 参数指定语言环境后,输出的日期字符串。
const date = new Date(Date.UTC(2012, 11, 20, 3, 0, 0));
// en-US 使用 month-day-year 的顺序展示年月日
date.toLocaleString('en-US', { timeZone: 'America/Los_Angeles' }); // '12/19/2012, 7:00:00 PM'
// en-GB 使用 day-month-year 顺序展示年月日
date.toLocaleString('en-GB', { timeZone: 'UTC' }); // // '20/12/2012 03:00:00'
// 韩语使用 year-month-day 顺序展示年月日
date.toLocaleString('ko-KR', { timeZone: 'Asia/Seoul' }); // '2012. 12. 20. 오후 12:00:00'
// 在日本,程序可能想指定使用日本日历,
// 2012是平成24年(平成是日本天皇明仁的年号, 由1989年1月8日起开始计算直至现在)
date.toLocaleString('ja-JP-u-ca-japanese', { timeZone: 'Asia/Tokyo' }); // '24/12/20 12:00:00'
// 当请求一个语言可能不支持,如巴厘(ban),若有备用的语言印尼语(id),那么将使用印尼语(id)
date.toLocaleString(['ban', 'id']); // '20/12/2012 11.00.00'
使用 options 参数
可以使用 options 参数来自定义 toLocaleString 方法返回的字符串。
const date = new Date(Date.UTC(2012, 11, 20, 3, 0, 0));
// options 包含参数 weekday,并且该参数的值为 long
const options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' };
date.toLocaleString('en-US', options); // 'Thursday, December 20, 2012'
// 指定 timeZone 为 'UTC'
options.timeZone = 'UTC';
// 不指定 timeZoneName 仍然显示的是世界标准时间,但是 UTC 三个字母不会显示
options.timeZoneName = 'short';
date.toLocaleString('en-US', options); // 'Thursday, December 20, 2012, UTC'
// 使用24小时制
date.toLocaleString('en-US', { hour12: false }); // '12/19/2012, 19:00:00'
其他文章链接
[译文]一步步构建发布一个 TypeScript NPM 包