是否有内置的方法来规范 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 从工作日获取日期

隐藏luxon中的无效日期

Luxon HH:mm 日期时间之间的差异

是否有符合标准的方法来检测 C 标准库中的函数是否通过内部/内置实现?

将 Luxon 日期格式化为 ISO8601 基本格式

如何在 Luxon 中使用 diff 方法