欢迎大家来到IT世界,在知识的湖畔探索吧!
大家好,很高兴又见面了,我是”高级前端进阶”,由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!
欢迎大家来到IT世界,在知识的湖畔探索吧!
1. 什么是 Intl.DurationFormat API
Intl.DurationFormat 对象用于语言敏感的持续时间的格式化,工作原理如下:
- 给定一个语言环境,默认为浏览器语言环境,即 navigator.language
- 给定一组表示不同单位(天、小时等)时间的值
- 给定一个时间样式,例如:long、short、narrow、digital
- 以所需的语言环境显示持续时间
例如,开发者可以如下定义持续时间:
let duration = { days: 1, hours: 5, minutes: 32 }
欢迎大家来到IT世界,在知识的湖畔探索吧!
接着生成一个持续时间的本地化字符串:
欢迎大家来到IT世界,在知识的湖畔探索吧!let durationFormatter = new Intl.DurationFormat(navigator.language,{style: 'long'}); dur = durationFormatter.format(duration);
控制台打印结果为:’1 天 5 小时 32 分钟’,而如果将语言环境更改为 fr 则输出’1 jour, 5 heures et 32 minutes’。在语言为 fr 的同时设置 short 格式则输出’1 j, 5 h et 32 min’。short 格式更短,而数字格式看起来更像数字时钟,更适合少于一天的持续时间。例如,可以在上面的输入中仅传入小时和分钟,则会输出:5:32:00。
// 选择 digital 类型 let duration = { hours: 5, minutes: 32 } let durationFormatter = new Intl.DurationFormat('fr', { style: 'digital'}); dur = durationFormatter.format(duration);
更多示例可以参考下面的代码:
欢迎大家来到IT世界,在知识的湖畔探索吧!let $result = document.querySelector('#result'); const log = s => {$result.innerHTML += s + '<br>' }; let duration = { minutes: 360 } let locales = ['en','fr','de']; // 本地 let styles = ['long', 'short', 'narrow', 'digital']; // 输出的时间样式类型 locales.forEach(l => { styles.forEach(s => { let durationFormatter = new Intl.DurationFormat(l, { style: s}); log(`Locale: ${l}, Style: ${s}: ` + durationFormatter.format(duration)); }); log(''); });
2. 将 Intl.DurationFormat 与真实数据结合
既然必须以单位形式说明持续时间,那么该如何处理动态值?开发者不能简单的只取两个日期间的差,因为如果传递一个大数字,格式化程序会原样输出。例如:
let duration = { minutes: 360 }
输出结果是 360 分钟而非 6 小时。因此,接下来需要构建一个解决方案,尝试将时间分解为年、月、周、天、小时、分钟和秒。
首先添加两个日期字段:
欢迎大家来到IT世界,在知识的湖畔探索吧!<p> <label for="date1">Date 1</label> <input type="datetime-local" id="date1"> </p> <p> <label for="date2">Date 2</label> <input type="datetime-local" id="date2"> </p>
接着添加一个 select 样式:
<p> <label for="style">Style:</label> <select id="style"> <option>long</option> <option>short</option> <option>narrow</option> <option>digital</option> </select> </p>
接着下方是一个空 div 用于显示结果,整体代码如下:
欢迎大家来到IT世界,在知识的湖畔探索吧!let $result = document.querySelector('#result'); let $style = document.querySelector('#style'); let $date1 = document.querySelector('#date1'); let $date2 = document.querySelector('#date2'); // 添加事件 $date1.addEventListener('input', handleDuration, false); $date2.addEventListener('input', handleDuration, false); $style.addEventListener('change', handleDuration, false);
接下来,定义一组表示持续时间单位的常量。
const MINUTE = 60 * 1000; const HOUR = 60 * MINUTE; const DAY = 24 * HOUR; const WEEK = 7 * DAY; // yeah, this is probably not perfect const MONTH = 4 * WEEK; const YEAR = MONTH * 12;
接下来就是表单字段更改运行的主逻辑:
欢迎大家来到IT世界,在知识的湖畔探索吧!function handleDuration() { let d1 = $date1.value; let d2 = $date2.value; if(!d1 || !d2) return; $result.innerHTML = ''; d1 = new Date(d1); d2 = new Date(d2); let diff = Math.abs(d1.getTime() - d2.getTime()); console.log(d1, d2, 'diff', diff); let durationFormatter = new Intl.DurationFormat(navigator.language, {style: $style.value}); let result = { years:0, months:0, weeks:0, days:0, hours:0, minutes:0, seconds:0 }; if(diff>= YEAR) { result.years = Math.floor(diff/YEAR); diff -= result.years * YEAR; } if(diff>= MONTH) { result.months = Math.floor(diff/MONTH); diff -= result.months * MONTH; } if(diff>= WEEK) { result.weeks = Math.floor(diff/WEEK); diff -= result.weeks * WEEK; } if(diff>= DAY) { result.days = Math.floor(diff/DAY); diff -= result.days * DAY; } if(diff>= HOUR) { result.hours = Math.floor(diff/HOUR); diff -= result.hours * HOUR; } if(diff>= MINUTE) { result.minutes = Math.floor(diff/MINUTE); diff -= result.minutes * MINUTE; } if(diff> 0) result.seconds = diff / 1000; console.log('Result',result); let test1Result = durationFormatter.format(result); $result.innerHTML += `First Result: ${test1Result}`; }
核心逻辑是根据持续时间(以毫秒为单位)是否大于一年、一个月等来构建一个持续时间结构,接着将结果传递给 format 函数并渲染。结果如下图所述:
3. Intl API 的扩展用法
除了上面提到的 DurationFormat 外,Intl 还支持 RelativeTimeFormat、DateTimeFormat 等与语言相关的时间格式化能力。当然,除了时间相关的能力外,还包括:数字(NumberFormat)、列表(ListFormat)等等其他格式化能力。
3.1 Intl.RelativeTimeFormat 相对时间格式化
除了上面语言相关的持续时间格式化外,Intl 还可用于诸多格式化场景,例如:相对时间的格式化。
const rtf1 = new Intl.RelativeTimeFormat("zh-CN", { style: "short"}); console.log(rtf1.format(3, "quarter")); // 输出: "三个季度后" console.log(rtf1.format(-1, "day")); // 输出: "1 天前" const rtf2 = new Intl.RelativeTimeFormat("es", { numeric: "auto"}); console.log(rtf2.format(2, "day")); // 输出: "pasado mañana"
3.2 Intl.DateTimeFormat 格式化日期和时间
Intl.DateTimeFormat 对象能使日期和时间在特定的语言环境下格式化。
欢迎大家来到IT世界,在知识的湖畔探索吧!const date = new Date(Date.UTC(2020, 11, 20, 3, 23, 16, 738)); // UTC 时区 console.log(new Intl.DateTimeFormat("en-US").format(date)); // 美东时间: "12/20/2020" console.log(new Intl.DateTimeFormat("zh-CN").format(date)); // 北京时间:"2020/12/20" // 使用 style 配置指定时间样式,例如: full, long, medium, short 等 console.log( new Intl.DateTimeFormat("en-GB", { dateStyle: "full", timeStyle: "long", timeZone: "Australia/Sydney", }).format(date), ); // 输出结果:"Sunday 20 December 2020 at 14:23:16 GMT+11"
参考资料
https://www.raymondcamden.com/2025/02/13/using-intldurationformat-for-localized-durations
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DurationFormat
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat
https://lokalise.com/blog/date-time-localization/
https://lenguajejs.com/javascript/fechas/formatear-fechas-con-intl/
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/128166.html