【发布时间】:2021-11-16 03:53:39
【问题描述】:
我有一个 ISO8601 持续时间字符串。前任。 “PT1M14S” 我想使用 typescript 中的 date-fns 包将其转换为秒(Int)
【问题讨论】:
标签: javascript typescript datetime iso8601 date-fns
我有一个 ISO8601 持续时间字符串。前任。 “PT1M14S” 我想使用 typescript 中的 date-fns 包将其转换为秒(Int)
【问题讨论】:
标签: javascript typescript datetime iso8601 date-fns
通过包提供一个解决方案:iso8601-duration 所以我们可以做类似的事情
import { parse, toSeconds } from 'iso8601-duration';
toSeconds(parse("PT1M14S"))
请告诉我 date-fns 对此提供了任何解决方案
【讨论】:
then.setMonth(then.getMonth() + duration.months) 不处理不同长度的飞蛾。通常有关于增加月份的业务规则,例如以这种方式将 1 个月添加到 1 月 31 日将在 3 月 2 日或 3 日结束(可能会或可能不会)。同样,由于某些地方的夏令时,在所有情况下添加 1 天并不等于添加 24 小时。加减持续时间可能不是对称的,因此如果dateA + durationA == dateB 则dateB - durationA == dateA 不一定为真。
解析 ISO 持续时间是问题的一半,将值应用于日期是另一半。以下是一个简单的解析器,它以{part: value} 的形式返回一个对象,例如:
{year: 1, month, 3, hour: 1, minute: 2}
它只返回字符串中标记的属性。需要添加一些体面的字符串验证。
function parseISODuration(s) {
// QnD validation of string, need something smarter
// Should check tokens, order and values
// e.g. decimals only in smallest unit, W excludes other date parts
if (!/^P/.test(s)) return;
// Split into parts
let parts = s.match(/\d+(\.\d+)?[a-z]|T/gi);
// Flag for date and time parts, used to disambiguate month and minute
let inDate = true;
// Map of part tokens to words
let partMap = {Y:'year',M:'month',W:'week',D:'day',h:'hour',m:'minute',s:'second'}
return parts.reduce((acc, part) => {
// Set flag if reached a time part
if (part == 'T') {
inDate = false;
return acc;
}
// Disambiguate time parts (month/minute)
if (!inDate) {
part = part.toLowerCase();
}
// Add part name and value as a number
acc[partMap[part.slice(-1)]] = +part.slice(0,-1);
return acc;
}, {});
}
// Examples
['P1Y2M1.5D', 'P1Y3M26DT3M', 'PT3H2M4.5S', 'P6W'].forEach(duration =>
console.log(`${duration} => ${JSON.stringify(parseISODuration(duration))}`)
);
将持续时间转换为毫秒并非易事,必须在开始日期的上下文中完成。一种方法是复制开始日期,添加适当的值(库当然可以提供帮助),然后获取开始日期和结束日期之间的差异。
这样,Date 实例和库会考虑不同月份长度和不同白天长度(观察夏令时)等问题,但这里有很多关于添加年、月、日的问题有很好的答案,等到某个日期,所以编写自己的函数来做到这一点并不难。
【讨论】: