Luxon中是否有内置的方法来标准化持续时间?

3
我正在从Momentjs迁移到Luxon。我允许用户选择任务所需的小时数。当我们保存这个值时,我希望它被标准化。因此,如果一个任务需要90个小时,我希望我们存储3天18小时。 我存储ISO Duration String,因此我想将PT90H转换为P3DT18H...当然,对于任何给定的值。
我尝试了Luxon的normalize函数,并尝试这样调用它:
const duration = Duration.fromObject({ hours: 90 });
duration.normalize().toISO();

然而,normalize 似乎对结果没有任何影响。我仍然得到 PT90H。在 Luxon 中有没有内置的方法可以实现这一点?

2个回答

5

Durtation.normalize()不会为Duration对象添加属性,因此您需要提供要归一化的单位。(对我来说这很奇怪,但可以隐式控制结果)。

normalize() – 将该Duration对象缩减至其当前单位下的规范表示。

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 - nephiw
说实话,我只会存储秒或毫秒。在前端进行算术转换是微不足道的。 - pilchard
1
但我不知道你从哪里得到了 PT0H20M,在上面的代码片段中 { hours: 0, minutes: 0, seconds: 1200} 转换为 ISO 格式后应该是 PT20M - pilchard
好观点,我没有通过Luxon运行那些值,你是正确的 Duration.fromObject({ hours: 0, minutes: 20 }).toISO() 会变成 PT20M 而不是 PT0H20M。这将使我的计算更简单,我不需要过滤掉值为0的单位。 - nephiw

3

根据 @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的单位的步骤是不必要的,toISO方法已经为我们做了这个操作。我的需求与让规范通过相关,似乎更好的方法是改变规范,而不是浪费CPU周期在计算期间进行单位归一化。使用上述方法将使得结果的ISO持续时间字符串单位归一化 - PT1H30M而不是PT90M
最终,我选择不使用0单位过滤,只允许在转换为ISO字符串时进行这种过滤。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接