是否有内置的方法来规范 Luxon 中的持续时间?
Posted
技术标签:
【中文标题】是否有内置的方法来规范 Luxon 中的持续时间?【英文标题】:Is there a built in way to normalize a duration within Luxon? 【发布时间】:2022-01-17 19:27:54 【问题描述】:我正在从 Momentjs 迁移到 Luxon。我允许用户选择任务将花费的小时数。当我们保存这个值时,我希望它正常化。因此,如果一项任务需要 90 小时,我希望我们存储 3 天 18 小时。我存储了 ISO 持续时间字符串,所以我想将 PT90H 转换为 P3DT18H...当然可以使用任何给定值。
我试过 Luxon 的 normalize
函数,我试着这样称呼它:
const duration = Duration.fromObject( hours: 90 );
duration.normalize().toISO();
但是,normalize
似乎对结果没有任何作用。我仍然得到PT90H。 Luxon 有内置的方法吗?
【问题讨论】:
【参考方案1】:Durtation.normalize()
不会向 Duration 对象添加属性,因此您需要提供您希望它标准化的单位。 (这对我来说很奇怪,但提供了对结果的隐含控制)。
normalize() – 将此持续时间减少为其规范表示在其当前单位。
const duration = Duration
.fromObject( days: 0, hours: 90 )
.normalize()
.toISO();
console.log(duration);
<script src="https://cdnjs.cloudflare.com/ajax/libs/luxon/2.2.0/luxon.min.js"></script>
<script>const Duration = luxon;</script>
您也可以使用Duration.shiftTo()
将持续时间显式强制为特定单位。
const duration = Duration
.fromObject(hours: 90 )
.shiftTo('days', 'hours')
.toISO();
console.log(duration);
<script src="https://cdnjs.cloudflare.com/ajax/libs/luxon/2.2.0/luxon.min.js"></script>
<script>const Duration = luxon;</script>
如果你知道你总是希望标准化为所有单位,你可以声明一个实用程序来返回一个用所有单位初始化的 Duration 对象。
function createDuration(duration)
return Duration.fromObject(
Object.assign(
years: 0, months: 0, weeks: 0, days: 0, hours: 0, minutes: 0, seconds: 0, milliseconds: 0 ,
duration
)
);
const duration = createDuration( hours: 90, minutes: 3004 ).normalize().toISO();
console.log(duration);
<script src="https://cdnjs.cloudflare.com/ajax/libs/luxon/2.2.0/luxon.min.js"></script>
<script>const Duration = luxon;</script>
【讨论】:
感谢您的回答,很遗憾 Luxon 不会为我优化这个。我真的不想将PT0H20M
存储到服务器,但我真的不想看到PT1200S
。
老实说,我只会存储秒或毫秒。算术转换在前端很简单。
...但我看不出你从哪里得到PT0H20M
, hours: 0, minutes: 0, seconds: 1200
toISO 在上面的 sn-ps 中产生PT20M
好点,我没有通过 Luxon 运行这些值,你是对的 Duration.fromObject( hours: 0, minutes: 20 ).toISO()
确实变成了 PT20M
而不是 PT0H20M
。这将使我的计算更简单,我不需要过滤掉 0 个值的单位。【参考方案2】:
根据@pilchard 的回答,我最终使用此函数来标准化我的持续时间。
function normalize(duration)
const durationObject = duration.shiftTo(
'years',
'months',
'days',
'hours',
'minutes',
'seconds'
).toObject();
// filter out units with 0 values.
const resultObject = Object.keys(durationObject).reduce((result, key) =>
const value = durationObject[key];
return value ? ...result, [key]: value : result;
, );
return Duration.fromObject(resultObject);
console.log(normalize(Duration.fromObject( hours: 90 )));
<script src="https://cdnjs.cloudflare.com/ajax/libs/luxon/2.2.0/luxon.min.js"></script>
<script>const Duration = luxon;</script>
[编辑]
我的既定目标不需要过滤掉 0'ed 单位的步骤,toISO
方法为我们完成了这项工作。我的需求与使规范通过有关,似乎更改规范比在计算过程中浪费 CPU 周期标准化更好。使用上述方法将使生成的 ISO 持续时间字符串标准化单位 - PT1H30M
而不是 PT90M
。
最后我选择不使用 0-unit 过滤,只在我将其转换为 ISO 字符串时允许它发生。
【讨论】:
以上是关于是否有内置的方法来规范 Luxon 中的持续时间?的主要内容,如果未能解决你的问题,请参考以下文章
在 javascript/nodejs 中使用 Luxon 从工作日获取日期