使用解析 date-fns 时排序不正确

Sorting is not correct when using parse date-fns

提问人:user3594118 提问时间:11/15/2022 最后编辑:user3594118 更新时间:11/15/2022 访问量:125

问:

我有 4 个日期,其中包含以下数据,但是当我对它们进行排序时,数据是错误的。

日期:


2h, 2m, 13s
5d, 3h, 49m, 42s
2h, 0m, 13s
12h, 32m, 13s

我正在尝试使用此公式使用 Date-fns 解析将它们转换为日期

     convertStringToDate(value) {
        if (value.match('M')) {
            return dateFns.parse(value, "M'M', dd'd', HH'h', mm'm', ss's'", new Date())
        }
        else if (value.match('d')) {
             return dateFns.parse(value, "dd'd', HH'h', mm'm', ss's'", new Date())
        }
        else if (value.match('h')) {
             return dateFns.parse(value, "HH'h', mm'm', ss's'", new Date())
        }
        else if (value.match('m')) {
             return dateFns.parse(value, "mm'm', ss's'", new Date())
        }
        else if (value.match('s')) {
             return dateFns.parse(value, "ss's'", new Date())
        }
    }

然后对其进行排序

$.fn.dataTableExt.oSort["customDuration-desc"] = (a, b) => {
                        a = this.convertStringToDate(a);
                        b = this.convertStringToDate(b);
                        return new Date(a) - new Date(b);
                    };

结果是错误的。 其显示为

5d, 3h, 49m, 42s
2h, 2m, 13s
2h, 0m, 13s
12h, 32m, 13s

而不是

5d, 3h, 49m, 42s
12h, 32m, 13s
2h, 2m, 13s
2h, 0m, 13s
javascript jquery 解析 日期-fns

评论

1赞 epascarello 11/15/2022
什么是“解析”
0赞 user3594118 11/15/2022
DateFns.parse 函数
0赞 pilchard 11/15/2022
你为什么期待你所指示的输出?它们按最早日期到最晚排序(您的实际输出顺序不正确)。看起来您的意思是按持续时间的长度排序,而不是按日期排序。
0赞 user3594118 11/15/2022
是的,我想按持续时间而不是日期对它们进行排序。
1赞 pilchard 11/15/2022
然后你需要把它们全部转换为一个等效的单位(秒?)并进行比较

答:

1赞 pilchard 11/15/2022 #1

您可以简单地解析持续时间字符串并将每个单位转换为秒,此处使用按单位缩写索引的对象来保存转换方法。(我已经删除了月份,因为没有标准的月份长度(以秒为单位)

function durationToSeconds(value) {
  const unitMap = {
    d: (d) => +d * 24 * 60 * 60,
    h: (h) => +h * 60 * 60,
    m: (m) => +m * 60,
    s: (s) => +s,
  }

  return value
    .split(',')
    .reduce((a, u) => {
      const { v, k } = u.match(/(?<v>\d+)(?<k>\w)/).groups
      return a + unitMap[k]?.(v) ?? 0;
    }, 0);
}

const input = [
  "2h, 2m, 13s",
  "5d, 3h, 49m, 42s",
  "2h, 0m, 13s",
  "12h, 32m, 13s"
];

const result = input.sort((a, b) => {
  a = durationToSeconds(a);
  b = durationToSeconds(b);

  return b - a;
});

console.log(result);

或者,您可以执行如下操作,该操作从字符串值创建一个持续时间对象,然后使用 date-fns.add() 将每个持续时间添加到预先指定的日期(此处保存在闭包中)。注意:在计算中引入日期会带来更多的复杂性,具体取决于您如何处理它们,时区/本地与 UTC/夏令时。

<script type='module'>
import { add } from 'https://esm.run/date-fns';

function addDuration(date) {
  const unitMap = {
    d: 'days',
    h: 'hours',
    m: 'minutes',
    s: 'seconds',
  }

  return (value) => {
    const duration = Object.assign(
      {
        years: 0,
        months: 0,
        weeks: 0,
        days: 0,
        hours: 0,
        minutes: 0,
        seconds: 0
      },
      Object.fromEntries(value.split(',').map(u => {
        const { v, k } = u.match(/(?<v>\d+)(?<k>\w)/).groups
        return [unitMap[k], v];
      }))
    );

    return add(date, duration)
  }
}

const addDurationToDate = addDuration(new Date());

const result = [
  "2h, 2m, 13s",
  "5d, 3h, 49m, 42s",
  "2h, 0m, 13s",
  "12h, 32m, 13s"
].sort((a, b) => {
  a = addDurationToDate(a);
  b = addDurationToDate(b);

  return b - a;
});

console.log(result);

</script>