不使用moment.js将ISO8601时长转换为对象的实现问询
手动解析ISO8601时长为原生对象
完全理解你的需求——不想为了两次转换引入整个moment.js,而且要严格保留原始时长单位(拒绝自动把天转成月/年)。其实手动解析ISO8601时长格式并不复杂,下面给你一个轻量的原生JavaScript实现:
实现思路
ISO8601时长的结构很固定:
- 以
P开头(Period的缩写) - 随后是日期部分:年(
Y)、月(M)、周(W)、日(D) - 如果包含时间部分,会以
T开头,接着是时(H)、分(M)、秒(S)
我们可以用正则表达式匹配出每个单位对应的数值,然后组装成你需要的可访问对象。
代码实现
function parseISO8601Duration(durationStr) { // 匹配ISO8601时长的正则,捕获各个单位的数值 const regex = /P(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)W)?(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?)?/; const matches = durationStr.match(regex); // 初始化默认值为0,确保所有属性都存在 const duration = { years: 0, months: 0, weeks: 0, days: 0, hours: 0, minutes: 0, seconds: 0 }; // 将捕获到的数值赋值到对应属性(注意matches数组索引从1开始) if (matches) { duration.years = parseInt(matches[1]) || 0; duration.months = parseInt(matches[2]) || 0; duration.weeks = parseInt(matches[3]) || 0; duration.days = parseInt(matches[4]) || 0; duration.hours = parseInt(matches[5]) || 0; duration.minutes = parseInt(matches[6]) || 0; duration.seconds = parseInt(matches[7]) || 0; } return duration; }
使用示例
const duration = parseISO8601Duration('P3Y2W1DT25H5M'); console.log(duration.years); // 3 console.log(duration.weeks); // 2 console.log(duration.days); // 1 console.log(duration.hours); // 25 console.log(duration.minutes); // 5 console.log(duration.months); // 0(原字符串无月单位) console.log(duration.seconds); // 0(原字符串无秒单位)
说明
- 这个实现完全保留原始单位,不会做任何自动转换(比如364天就是364天,不会转成月或年)
- 即使时长字符串缺少某些单位(比如只有日和时),返回的对象也会包含所有属性,默认值为0
- 正则表达式已经覆盖了常见的ISO8601时长格式,包括仅日期部分、仅时间部分、混合日期时间的情况
内容的提问来源于stack exchange,提问作者webdevverbe
相关产品推荐
相关产品推荐

