【译】你可能不需要Moment.js - 掘金

Moment存在的一些问题

  • 它高度基于OOP API,这使得它无法使用Webpack 2 新引入的Tree-shaking代码优化技术
  • 由于OOP API还有非纯函数,这会导致一些bug github.com/moment/mome…
  • 如果您没有使用时区,而只使用了moment.js中的一些简单函数,这会导致你的应用程序被引入了很多没使用的方法,这是极其浪费性能和内存的。 在这里推荐使用dayjs, dayjs有一个较小的核心,并且具有非常相似的API,因此很容易从moment平滑过渡到day.js。date-fns可以使用Tree-shaking代码优化技术和其他good api,因此它很适合与React,Sinon.js和webpack等好基友一起使用。

    字符串+日期格式化

    返回从字符串中解析的日期.
    1. // Moment.js
    2. moment('12-25-1995', 'MM-DD-YYYY');
    3. // => "1995-12-24T13:00:00.000Z"
    4. // date-fns
    5. import parse from 'date-fns/parse';
    6. parse('12-25-1995', 'MM-dd-yyyy', new Date());
    7. // => "1995-12-24T13:00:00.000Z"
    8. // dayjs
    9. dayjs('12-25-1995');
    10. // => "1995-12-24T13:00:00.000Z"
    11. 复制代码

字符串+时间格式化

返回从字符串中解析的时间日期.

  1. // Moment.js
  2. moment('2010-10-20 4:30', 'YYYY-MM-DD HH:mm');
  3. // => "2010-10-19T17:30:00.000Z"
  4. // date-fns
  5. import parse from 'date-fns/parse';
  6. parse('2010-10-20 4:30', 'yyyy-MM-dd H:mm', new Date());
  7. // => "2010-10-19T17:30:00.000Z"
  8. // dayjs❌不支持自定义格式解析
  9. 复制代码

字符串+本地格式化

返回从字符串中解析的本地化时间日期.

  1. // Moment.js
  2. moment('2012 mars', 'YYYY MMM', 'fr');
  3. // => "2012-02-29T13:00:00.000Z"
  4. // date-fns
  5. import parse from 'date-fns/parse';
  6. import fr from 'date-fns/locale/fr';
  7. parse('2012 mars', 'yyyy MMMM', new Date(), { locale: fr });
  8. // => "2012-02-29T13:00:00.000Z"
  9. // dayjs❌不支持自定义格式解析
  10. 复制代码

取值 + 赋值

毫秒/秒/分/时

获取 毫秒 / 秒 / 分 / 时

  1. // Moment.js
  2. moment().seconds();
  3. // => 49
  4. moment().hours();
  5. // => 19
  6. // 原生
  7. new Date().getSeconds();
  8. // => 49
  9. new Date().getHours();
  10. // => 19
  11. // date-fns
  12. import getSeconds from 'date-fns/getSeconds';
  13. import getHours from 'date-fns/getHours';
  14. getSeconds(new Date());
  15. // => 49
  16. getHours(new Date());
  17. // => 19
  18. // dayjs
  19. dayjs().second();
  20. // => 49
  21. dayjs().hour();
  22. // => 19
  23. 复制代码

设置 毫秒 / 秒 / 分 / 时

  1. // Moment.js
  2. moment().seconds(30);
  3. // => "2018-09-09T09:12:30.695Z"
  4. moment().hours(13);
  5. // => "2018-09-09T03:12:49.695Z"
  6. // 原生
  7. new Date(new Date().setSeconds(30));
  8. // => "2018-09-09T09:12:30.695Z"
  9. new Date(new Date().setHours(13));
  10. // => "2018-09-09T03:12:49.695Z"
  11. // date-fns
  12. import setSeconds from 'date-fns/setSeconds';
  13. import setHours from 'date-fns/setHours';
  14. setSeconds(new Date(), 30);
  15. // => "2018-09-09T09:12:30.695Z"
  16. setHours(new Date(), 13);
  17. // => "2018-09-09T03:12:49.695Z"
  18. // dayjs
  19. dayjs().set('second', 30);
  20. // => "2018-09-09T09:12:30.695Z"
  21. dayjs().set('hour', 13);
  22. // => "2018-09-09T03:12:49.695Z"
  23. 复制代码

月份日期

设置&获取月份。

  1. // Moment.js
  2. moment().date();
  3. // => 9
  4. moment().date(4);
  5. // => "2018-09-04T09:12:49.695Z"
  6. // 原生
  7. new Date().getDate();
  8. // => 9
  9. new Date().setDate(4);
  10. // => "2018-09-04T09:12:49.695Z"
  11. // date-fns
  12. import getDate from 'date-fns/getDate';
  13. import setDate from 'date-fns/setDate';
  14. getDate(new Date());
  15. // => 9
  16. setDate(new Date(), 4);
  17. // => "2018-09-04T09:12:49.695Z"
  18. // dayjs
  19. dayjs().date();
  20. // => 9
  21. dayjs().set('date', 4);
  22. // => "2018-09-04T09:12:49.6
  23. 复制代码

星期几

设置&获取星期。

  1. // Moment.js
  2. moment().day();
  3. // => 0 (Sunday)
  4. moment().day(-14);
  5. // => "2018-08-26T09:12:49.695Z"
  6. // 原生
  7. new Date().getDay();
  8. // => 0 (Sunday)
  9. new Date().setDate(new Date().getDate() - 14);
  10. // => "2018-08-26T09:12:49.695Z"
  11. // date-fns
  12. import getDay from 'date-fns/getDay';
  13. import setDay from 'date-fns/setDay';
  14. getDay(new Date());
  15. // => 0 (Sunday)
  16. setDay(new Date(), -14);
  17. // => "2018-08-26T09:12:49.695Z"
  18. // dayjs
  19. dayjs().day();
  20. // => 0 (Sunday)
  21. dayjs().set('day', -14);
  22. // => "2018-08-26T09:12:49.695Z"
  23. 复制代码

一年的某一天

设置&获取一年的某一天。

  1. // Moment.js
  2. moment().dayOfYear();
  3. // => 252
  4. moment().dayOfYear(256);
  5. // => "2018-09-13T09:12:49.695Z"
  6. // date-fns
  7. import getDayOfYear from 'date-fns/getDayOfYear';
  8. import setDayOfYear from 'date-fns/setDayOfYear';
  9. getDayOfYear(new Date());
  10. // => 252
  11. setDayOfYear(new Date(), 256);
  12. // => "2018-09-13T09:12:49.695Z"
  13. // dayjs ❌ 不支持
  14. 复制代码

一年的某一周

设置&获取一年的某一周。

  1. // Moment.js
  2. moment().week();
  3. // => 37
  4. moment().week(24);
  5. // => "2018-06-10T09:12:49.695Z"
  6. // date-fns
  7. import getWeek from 'date-fns/getWeek';
  8. import setWeek from 'date-fns/setWeek';
  9. getWeek(new Date());
  10. // => 37
  11. setWeek(new Date(), 24);
  12. // => "2018-06-10T09:12:49.695Z"
  13. // dayjs ⚠️ requires weekOfYear plugin
  14. import weekOfYear from 'dayjs/plugin/weekOfYear';
  15. dayjs.extend(weekOfYear);
  16. dayjs().week();
  17. // => 37
  18. // dayjs ❌ 不支持
  19. 复制代码

某月有多少天

获取某月有多少天。

  1. // Moment.js
  2. moment('2012-02', 'YYYY-MM').daysInMonth();
  3. // => 29
  4. // date-fns
  5. import getDaysInMonth from 'date-fns/getDaysInMonth';
  6. getDaysInMonth(new Date(2012, 1));
  7. // => 29
  8. // dayjs
  9. dayjs('2012-02').daysInMonth();
  10. // => 29
  11. 复制代码

一年有多少周

根据ISO周,获取当年的周数。

  1. // Moment.js
  2. moment().isoWeeksInYear();
  3. // => 52
  4. // date-fns
  5. import getISOWeeksInYear from 'date-fns/getISOWeeksInYear';
  6. getISOWeeksInYear(new Date());
  7. // => 52
  8. // dayjs ❌ does not support weeks in the year
  9. 复制代码

获取日期最大值

返回给定日期的最大值。

  1. const array = [
  2. new Date(2017, 4, 13),
  3. new Date(2018, 2, 12),
  4. new Date(2016, 0, 10),
  5. new Date(2016, 0, 9),
  6. ];
  7. // Moment.js
  8. moment.max(array.map(a => moment(a)));
  9. // => "2018-03-11T13:00:00.000Z"
  10. // 原生
  11. new Date(Math.max.apply(null, array)).toISOString();
  12. // => "2018-03-11T13:00:00.000Z"
  13. // date-fns
  14. import max from 'date-fns/max';
  15. max(array);
  16. // => "2018-03-11T13:00:00.000Z"
  17. // dayjs ❌ 不支持
  18. 复制代码

获取日期最小值

返回给定日期的最小值。

  1. const array = [
  2. new Date(2017, 4, 13),
  3. new Date(2018, 2, 12),
  4. new Date(2016, 0, 10),
  5. new Date(2016, 0, 9),
  6. ];
  7. // Moment.js
  8. moment.min(array.map(a => moment(a)));
  9. // => "2016-01-08T13:00:00.000Z"
  10. // 原生
  11. new Date(Math.min.apply(null, array)).toISOString();
  12. // => "2016-01-08T13:00:00.000Z"
  13. // date-fns
  14. import min from 'date-fns/min';
  15. min(array);
  16. // => "2016-01-08T13:00:00.000Z"
  17. // dayjs ❌ 不支持
  18. 复制代码

操作比较

添加天数

将指定的天数添加到给定日期。

  1. // Moment.js
  2. moment().add(7, 'days');
  3. // => "2018-09-16T09:12:49.695Z"
  4. // date-fns
  5. import addDays from 'date-fns/addDays';
  6. addDays(new Date(), 7);
  7. // => "2018-09-16T09:12:49.695Z"
  8. // dayjs
  9. dayjs().add(7, 'day');
  10. // => "2018-09-16T09:12:49.695Z"
  11. 复制代码

减去天数

从给定日期减去指定的天数。

  1. // Moment.js
  2. moment().subtract(7, 'days');
  3. // => "2018-09-02T09:12:49.695Z"
  4. // date-fns
  5. import subDays from 'date-fns/subDays';
  6. subDays(new Date(), 7);
  7. // => "2018-09-02T09:12:49.695Z"
  8. // dayjs
  9. dayjs().subtract(7, 'day');
  10. // => "2018-09-02T09:12:49.695Z"
  11. 复制代码

获月初时间

获取这个月初时间。

  1. // Moment.js
  2. moment().startOf('month');
  3. // => "2018-08-31T14:00:00.000Z"
  4. // date-fns
  5. import startOfMonth from 'date-fns/startOfMonth';
  6. startOfMonth(new Date());
  7. // => "2018-08-31T14:00:00.000Z"
  8. // dayjs
  9. dayjs().startOf('month');
  10. // => "2018-08-31T14:00:00.000Z"
  11. 复制代码

获取今天结束的时间

获取今天结束的时间。

  1. // Moment.js
  2. moment().endOf('day');
  3. // => "2018-09-09T13:59:59.999Z"
  4. // date-fns
  5. import endOfDay from 'date-fns/endOfDay';
  6. endOfDay(new Date());
  7. // => "2018-09-09T13:59:59.999Z"
  8. // dayjs
  9. dayjs().endOf('day');
  10. // => "2018-09-09T13:59:59.999Z"
  11. 复制代码

显示

格式化

用给定的格式格式化给定的字符串。

  1. // Moment.js
  2. moment().format('dddd, MMMM Do YYYY, h:mm:ss A');
  3. // => "Sunday, September 9th 2018, 7:12:49 PM"
  4. moment().format('ddd, hA');
  5. // => "Sun, 7PM"
  6. // date-fns
  7. import format from 'date-fns/format';
  8. format(new Date(), 'eeee, MMMM do YYYY, h:mm:ss aa');
  9. // => "Sunday, September 9th 2018, 7:12:49 PM"
  10. format(new Date(), 'eee, ha');
  11. // => "Sun, 7PM"
  12. // dayjs
  13. dayjs().format('dddd, MMMM D YYYY, h:mm:ss A');
  14. // => "Sunday, September 9 2018, 7:12:49 PM" ⚠️ not support 9th
  15. dayjs().format('ddd, hA');
  16. // => "Sun, 7PM"
  17. 复制代码

获取到现在的年限

获取到现在的年限

  1. // Moment.js
  2. moment(1536484369695).fromNow();
  3. // => "4 days ago"
  4. // date-fns
  5. import formatDistance from 'date-fns/formatDistance';
  6. formatDistance(new Date(1536484369695), new Date(), { addSuffix: true });
  7. // => "4 days ago"
  8. // dayjs ⚠️ requires relativeTime plugin
  9. import relativeTime from 'dayjs/plugin/relativeTime';
  10. dayjs.extend(relativeTime);
  11. dayjs(1536484369695).fromNow();
  12. // => "5 days ago" ⚠️ 这个插件的舍入方法与moment.js和date-fns不同,请谨慎使用。
  13. 复制代码

时差

返回两个时间点的时差。

  1. // Moment.js
  2. moment([2007, 0, 27]).to(moment([2007, 0, 29]));
  3. // => "in 2 days"
  4. // date-fns
  5. import formatDistance from 'date-fns/formatDistance';
  6. formatDistance(new Date(2007, 0, 27), new Date(2007, 0, 29));
  7. // => "2 days"
  8. // dayjs ⚠️ 需要relativeTime插件
  9. import relativeTime from 'dayjs/plugin/relativeTime';
  10. dayjs.extend(relativeTime);
  11. dayjs('2007-01-27').to(dayjs('2007-01-29'));
  12. // => "in 2 days"
  13. 复制代码

时差(毫秒)

返回两个时间点的毫秒级时差。

  1. // Moment.js
  2. moment([2007, 0, 27]).diff(moment([2007, 0, 29]));
  3. // => -172800000
  4. moment([2007, 0, 27]).diff(moment([2007, 0, 29]), 'days');
  5. // => -2
  6. // date-fns
  7. import differenceInMilliseconds from 'date-fns/differenceInMilliseconds';
  8. differenceInMilliseconds(new Date(2007, 0, 27), new Date(2007, 0, 29));
  9. // => -172800000
  10. import differenceInDays from 'date-fns/differenceInDays';
  11. differenceInDays(new Date(2007, 0, 27), new Date(2007, 0, 29));
  12. // => -2
  13. // dayjs
  14. dayjs('2007-01-27').diff(dayjs('2007-01-29'), 'milliseconds');
  15. // => -172800000
  16. dayjs('2007-01-27').diff(dayjs('2007-01-29'), 'days');
  17. // => -2
  18. 复制代码

查询

是否之前

检查日期是否在另一个日期之前。

  1. // Moment.js
  2. moment('2010-10-20').isBefore('2010-10-21');
  3. // => true
  4. // date-fns
  5. import isBefore from 'date-fns/isBefore';
  6. isBefore(new Date(2010, 9, 20), new Date(2010, 9, 21));
  7. // => true
  8. // dayjs
  9. dayjs('2010-10-20').isBefore('2010-10-21');
  10. // => true
  11. 复制代码

是否一样

检查日期是否与另一个日期相同。

  1. // Moment.js
  2. moment('2010-10-20').isSame('2010-10-21');
  3. // => false
  4. moment('2010-10-20').isSame('2010-10-20');
  5. // => true
  6. moment('2010-10-20').isSame('2010-10-21', 'month');
  7. // => true
  8. // date-fns
  9. import isSameDay from 'date-fns/isSameDay';
  10. import isSameMonth from 'date-fns/isSameMonth';
  11. isSameDay(new Date(2010, 9, 20), new Date(2010, 9, 21));
  12. // => false
  13. isSameDay(new Date(2010, 9, 20), new Date(2010, 9, 20));
  14. // => true
  15. isSameMonth(new Date(2010, 9, 20), new Date(2010, 9, 21));
  16. // => true
  17. // dayjs
  18. dayjs('2010-10-20').isSame('2010-10-21');
  19. // => false
  20. dayjs('2010-10-20').isSame('2010-10-20');
  21. // => true
  22. // dayjs ❌ 不支持
  23. 复制代码

是否之后

检查日期是否在另一个日期之后。

  1. // Moment.js
  2. moment('2010-10-20').isAfter('2010-10-19');
  3. // => true
  4. // date-fns
  5. import isAfter from 'date-fns/isAfter';
  6. isAfter(new Date(2010, 9, 20), new Date(2010, 9, 19));
  7. // => true
  8. // dayjs
  9. dayjs('2010-10-20').isAfter('2010-10-19');
  10. // => true
  11. 复制代码

是否在两个日期之前

检查日期是否在两个其他日期之间。

  1. // Moment.js
  2. moment('2010-10-20').isBetween('2010-10-19', '2010-10-25');
  3. // => true
  4. // date-fns
  5. import isWithinInterval from 'date-fns/isWithinInterval';
  6. isWithinInterval(new Date(2010, 9, 20), {
  7. start: new Date(2010, 9, 19),
  8. end: new Date(2010, 9, 25),
  9. });
  10. // => true
  11. // dayjs ⚠️ requires isBetween plugin
  12. import isBetween from 'dayjs/plugin/isBetween';
  13. dayjs.extend(isBetween);
  14. dayjs('2010-10-20').isBetween('2010-10-19', '2010-10-25');
  15. // => true
  16. 复制代码

是否是闰年

判断是否是润年。

  1. // Moment.js
  2. moment([2000]).isLeapYear();
  3. // => true
  4. // date-fns
  5. import isLeapYear from 'date-fns/isLeapYear';
  6. isLeapYear(new Date(2000, 0, 1));
  7. // => true
  8. // dayjs ⚠️ 要引入 isLeapYear 插件
  9. import isLeapYear from 'dayjs/plugin/isLeapYear';
  10. dayjs.extend(isLeapYear);
  11. dayjs('2000').isLeapYear();
  12. // => true
  13. 复制代码

是否是日期对象

检查变量是否是js Date对象。

  1. // Moment.js
  2. moment.isDate(new Date());
  3. // => true
  4. // date-fns
  5. import isDate from 'date-fns/isDate';
  6. isDate(new Date());
  7. // => true
  8. // dayjs ❌ 不支持
  9. 复制代码

总结

如果你只需要简单的操作那么day.js更适合你,如果复杂一点的项目那么date-fns看起来更合适。
如果你只是用momentjs中的两三个方法,则完全可以考虑使用其他更加轻量、性能更加好的库,或者使用JavaScript原生的方法,必要时封装一下即可。如果程序对性能有较高的要求,最好不要使用momentjs