如何转换ISO时长为可读格式 解决luxon搭配humanize-duration转换误差问题
偏差原因
humanize-duration 基于毫秒值做时长换算,默认使用固定换算规则:1年=365天、1月=30天。你直接将Luxon的Duration对象传入时,库会先将其转换为总毫秒数再拆分,完全丢失了ISO 8601时长定义的原生年、月、日字段值,因此出现换算偏差。
解决方案
方案1:使用Luxon自带的toHuman方法(最推荐)
Luxon本身就支持时长人性化转换,完全保留原始ISO时长的字段值,无需额外引入第三方库:
transform(value: string): string { console.log(value); const formattedIso = Duration.fromISO(value); // 指定转换单位和显示格式 return formattedIso.toHuman({ unitDisplay: 'long', units: ['year', 'month', 'day'] }); }
转换效果和ISO定义完全一致:
- 输入
P1Y11M3D输出1 year, 11 months, 3 days - 输入
P2Y1M30D输出2 years, 1 month, 30 days
如果需要中文显示,只需提前配置Luxon的本地化参数为zh-CN,即可直接输出1年,11个月,3天格式的内容。
方案2:必须使用humanize-duration时的处理逻辑
手动从Luxon Duration实例中提取原始的年、月、日数值,跳过库的自动毫秒换算逻辑:
transform(value: string): string { console.log(value); const formattedIso = Duration.fromISO(value); const unitValues = { y: formattedIso.years, mo: formattedIso.months, d: formattedIso.days }; const parts = []; if (unitValues.y) parts.push(unitValues.y === 1 ? '1 year' : `${unitValues.y} years`); if (unitValues.mo) parts.push(unitValues.mo === 1 ? '1 month' : `${unitValues.mo} months`); if (unitValues.d) parts.push(unitValues.d === 1 ? '1 day' : `${unitValues.d} days`); return parts.join(', '); }
内容的提问来源于stack exchange,提问作者Mike S
相关产品推荐
相关产品推荐

