如何将ISO 8601时长字符串格式化为XhYm格式?求解决建议
解决ISO 8601时长转XhYm格式的问题
嘿,我来帮你搞定这个格式转换的需求~先说说你当前代码的问题:用moment.utc(duration.asMilliseconds()).format('HH:mm')得到的是类似01:20的时间格式,不仅和你要的1h20m形式不符,而且如果时长超过24小时,HH会被重置为01,没法正确显示累计时长。下面给你几个可行的解决方案:
方案一:基于现有moment.js代码修改
既然你已经在用moment,直接利用moment.duration提供的方法来提取小时和分钟,再拼接成想要的格式就行,还能处理超过24小时的情况:
const duration = moment.duration(secondData.duration); // 把天数转成小时,避免超过24小时时丢失时长 const totalHours = duration.days() * 24 + duration.hours(); const minutes = duration.minutes(); let formatted = ''; // 有小时就显示Xh if (totalHours > 0) { formatted += `${totalHours}h`; } // 有分钟或者没有小时时显示Ym(比如0h30m直接显示30m) if (minutes > 0 || totalHours === 0) { formatted += `${minutes}m`; }
比如:
- 输入
PT1H20M→ 输出1h20m - 输入
P1DT2H30M(1天2小时30分)→ 输出26h30m - 输入
PT45M→ 输出45m
方案二:原生JS解析(不依赖moment)
如果不想用第三方库,用正则表达式直接解析ISO 8601时长字符串也很方便:
function formatDurationToXhYm(durationStr) { // 匹配ISO 8601中的天、小时、分钟(可根据需求扩展秒等单位) const match = durationStr.match(/P(?:(\d+)D)?T(?:(\d+)H)?(?:(\d+)M)?/); const days = match[1] ? parseInt(match[1], 10) : 0; const hours = match[2] ? parseInt(match[2], 10) : 0; const minutes = match[3] ? parseInt(match[3], 10) : 0; const totalHours = days * 24 + hours; let result = ''; if (totalHours > 0) { result += `${totalHours}h`; } if (minutes > 0 || totalHours === 0) { result += `${minutes}m`; } return result; } // 调用示例 console.log(formatDurationToXhYm('PT1H20M')); // "1h20m" console.log(formatDurationToXhYm('P2DT3H')); // "51h0m"(如果不想显示0m,可以加判断去掉)
如果不需要处理天的话,正则可以简化成/PT(?:(\d+)H)?(?:(\d+)M)?/。
方案三:用现代JS的Intl.DurationFormat(注意兼容性)
如果你运行代码的环境支持ES2022+,可以用原生的Intl.DurationFormat API,不过需要稍微处理一下格式:
// 先把ISO 8601时长转成Duration对象的结构(可以用moment或者正则提取) const durationObj = moment.duration(secondData.duration).toObject(); const totalHours = durationObj.days * 24 + durationObj.hours; const formatter = new Intl.DurationFormat('en', { hours: 'numeric', minutes: 'numeric', style: 'short' }); // 把默认的"1 hr 20 min"替换成"1h20m" const formatted = formatter.format({ hours: totalHours, minutes: durationObj.minutes }) .replace(' hr ', 'h') .replace(' min', 'm');
这个方法更原生,但要注意旧版浏览器(比如IE)不支持。
内容的提问来源于stack exchange,提问作者user8991667
相关产品推荐
相关产品推荐

