1 现状和问题
moment.js 是大而全的时间处理的js时间库,现已广泛应用于数百万个项目中。它所提供的功能基本上能覆盖所有关于时间转换和解析相关的问题,而且它的API介绍清晰简单,使用起来和写法也是相当简单。但是缺点也是很明显的,这个在最后面捎带着说两句。今天主要是给大家总结一下它的一些使用方法和一些坑点。
2 moment 使用和安装
目前moment的最新版本是一年前发布的2.29.4。
安装 npm i moment.js -S 或者 yarn add moment.js -S
使用 import moment from 'moment';
3 moment 的API使用
3.1 解析方面
moment(string?) 解析成当前所在时区的时间,不管你传入参数是否是否包含offset。
moment().format()
'2023-08-07T16:57:13+08:00'
moment('2023-08-07T16:57:13-08:00').format()
'2023-08-08T08:57:13+08:00'
该字符串需符合 ISO8601 strings 格式,如果不是如何以上,将会moment('not data').isValid() -false
moment(string?).format(token?) 可以解析成你需要的格式的时间 其中toke有以下几种表示方法
Y- year. M-month D-day H-hour m-Minutes s-Seconds X-unix timestamp x-Unix ms timestamp
moment().format('YYYY-MM-DD HH:mm:ss') '2023-08-07 17:26:26'
moment().format('YYYY-MM-DDTHH:mm:ss.SSS') '2023-08-07T17:27:12.378'
moment().format('YYYY-MM-DDTHH:mm:ss.SSSZ') '2023-08-07T17:27:44.665+08:00'
moment({unit:value,...}) 可以传入一个带时间单位的对象生成一个moment
moment({ year :2010, month :3, day :5, hour :15, minute :10, second :3, millisecond :123});
moment(Number) 传入毫秒级timestamp moment.unix(Number)传入秒级timestamp
moment(1318781876406).format() '2011-10-17T00:17:56+08:00' moment.unix(1318781876).format() '2011-10-17T00:17:56+08:00' moment.unix(1318781876.721).format() '2011-10-17T00:17:56+08:00'
moment(Date) 参数为js内置对象类型
moment(new Date()).format() '2023-08-07T17:37:34+08:00'
moment(Moment) 参数为moment 类型,由于moment 数据类型是可变的,所以在某些场景下做出了更改,不想要更改原始数据,需要clone。也可以用moment().clone(),来实现。
var a = moment([2012]);
var b = moment(a);
a.year(2000);
b.year(); // 2012
2012
2.1 moment.utc 默认状态下moment是以本地时间去解析和呈现的utc时间
moment().format()
'2023-08-07T18:00:29+08:00'
moment.utc().format()
'2023-08-07T10:00:40Z'
moment.parseZone 与moment.utcOffset 作用一致 解析提供的字符串,并将生成的时刻保留在固定的时区中。将生成的 Moment 对象保留在固定偏移量时区中,并在字符串中提供偏移量。
moment().utcOffset(number| string,boolean?:false) 设置utc偏移量(其中是分钟为单位的)
当设置的参数-16 to 16时,此时输入的参数单位是以hour计算,如果不在这个范围时,将以分钟为单位计算如下例子,传入8或480得到的偏移量时一样的;
moment().utcOffset(8).utcOffset()
480
moment().utcOffset(480).utcOffset()
480
设置的参数也可以为字符串,像 "+08:00" 这种类型,比如
moment().utcOffset("+08:00").utcOffset(); 480
注意:如果需要传入是时区名称的话,比如‘America/Los_Angeles’ 就要使用moment-timezone.插件
此方法还有第二个参数,是为了显示是否保留一天中的现有时间,参数默认为false
moment().utcOffset("+09:00").format() '2023-08-08T16:11:23+09:00' moment().utcOffset("+09:00", true).format() '2023-08-08T15:11:26+09:00'
如以上例子所示,当前浏览器所在时间为15:11:26 当参数为true,时得到的时间与本地相同,但是世界时间确实不同的,我们可以通过时间戳来看一下,时间一样的话,时间戳肯定是一样的,如下举例所示,果然在世界时间是不同的两个时间。
moment('2023-08-08 16:17:25').utcOffset("+09:00").valueOf()
1691482645000
moment('2023-08-08 16:17:25').utcOffset("+09:00", true).valueOf()
1691479045000
3 Get/Set
获取小时、分钟、秒、毫秒
moment().hour(number?) 参数范围0-23 超出将会累加到day上
moment().minute(number?) 参数范围0-59 超出将会累加hour上
moment().second(number?) 参数范围0-59 超出将会累加minute上
moment().millisecond(number?) 参数范围0-999 超出将会累加second上以此类推
月里的第几天
moment().date(number?) 参数范围1-31 超出将会累加到month上
周里的第几天
moment().day(number?) 参数范围0-7 超出将会累加另外一周
年里的第几天
moment().dayOfYear(number?) 参数范围1-366 超出将会累加另外一年
年里的第几周
moment().week(number?) 不同地区的,会不一样
获取或设置第几月
moment().month(string? | number?) 这里需要注意的是,月是从0开始的,所以1月Januarymonth()为0,以此类推。参数可以为字符串时,January、Feb。参数也可以为数字时范围是0-11 超出将会累积到另外一年。
获取或设置第几季度
moment().quarter() 范围是1-4
获取或设置年
moment().year() 范围是 -270,000 to 270,000
也可以通过get或者set来获取对应时间和设置对应时间
moment().get(unit) unit其中可以为 --> year(y)、month(M)、date (D), hour (h), minute (m), second (s), millisecond (ms).
moment().set(unit, number) unit同get 一致
比较大小
moment.max(Moment[]| Moment[,Moment...]) 和moment.min(Moment[]| Moment[,Moment...])
操作
增加时间
moment().add(numer, unit) unit 是时间单位缩写,
moment().subtract(number,unit) 缩短时间
moment().startOf(string) 设置时间到一个单位的开始时间,下面是具体例子,注意看下划线的部分。
moment().startOf('year').format() '2023-01-01T00:00:00+08:00' moment().startOf('month').format() '2023-08-01T00:00:00+08:00' moment().startOf('quarter').format() '2023-07-01T00:00:00+08:00' moment().startOf('week').format() '2023-08-06T00:00:00+08:00' moment().startOf('day').format() '2023-08-08T00:00:00+08:00' moment().startOf('date').format() '2023-08-08T00:00:00+08:00' moment().startOf('hour').format() '2023-08-08T14:00:00+08:00' moment().startOf('minute').format() '2023-08-08T14:40:00+08:00' moment().startOf('second').format() '2023-08-08T14:41:04+08:00'
moment().endOf(string) 设置时间到一个单位的结束时间,如:
moment().endOf('day').format()
'2023-08-08T23:59:59+08:00'
展现
format 默认是ISOString 格式去展现的,参数可以传入对应的格式
moment().format(string?);
moment().diff(Moment|String|number|Date|Array,string?,boolean) 测量两个时间测差值,通常以毫秒为单位。如果以具体的单位粒度去测量差值,只需要传入第二个对应的参数即可。
moment('2023-08-09').diff(moment('2023-08-08'))
86400000
moment('2023-08-09').diff(moment('2023-08-08'), 'd')
1
第三个参数是指 是否将结果四舍五入带接近的整数的数字,默认情况下是取整的。如以下例子:
var a = moment([2008, 9]);
var b = moment([2007, 0]);
a.diff(b, 'years'); // 1
a.diff(b, 'years', true); // 1.75
时间戳
moment().valueOf() 获取毫秒级时间戳
moment().unix() 获取妙级时间戳
转换格式
转换成ISO8601String moment().toISOString() '2023-08-08T10:56:54.993Z'
转换成 js 原生Date类型 moment().toDate(); Tue Aug 08 2023 18:57:42 GMT+0800 (中国标准时间)
转换成Object moment().toObject(); {years: 2023, months: 7, date: 8, hours: 18, minutes: 59, …}
转换成数组 moment().toArray(); (7) [2023, 7, 8, 19, 0, 51, 935]
查询
moment().isBefore(Moment|String|number|Date|Array,string) 检查一个时间是否在另一个时间之前
moment('2010-10-20').isBefore('2010-10-21'); // true
如果时间粒度的限制是毫秒以外的单位,可以通过第二个参数进行传递
moment('2010-10-20').isBefore('2010-12-31', 'year'); // false
moment().isSame(Moment|String|number|Date|Array,string) 和moment().isAfter(Moment|String|number|Date|Array,string) 就表示相同或者是否在之后
moment().isSameOrBefore() 和moment().isSameOrAfter() 则表示,时间的对比<= 或者>=
moment().isBetween(Moment|String|Number|Date|Array, Moment|String|Number|Date|Array)用来判断目标时间是否一个时间范围内
moment('2010-10-20').isBetween('2010-10-19', '2010-10-25'); // true
注意:isBetween中的参数顺序有大小前后顺序,时间小的应放在最前面。
moment.isData(obj) 判断对象是不是原生js Date类型
moment.isMoment(obj) 判断对象是不是moment类型
3 webpack 打包减少moment体积 按需引入
使用插件IgnorePlugin插件,它会移除moment的所有本地文件
使用方式 第一步在webpack plugins 配置
const webpack = require('webpack');
module.exports = {
//...
plugins: [
// 忽略 moment.js的所有本地文件
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
],
};
4 展望
moment.js 官方文档中Project Status说他们正式宣布进入维护期,已不在开发新功能了。这就意味着他们不会解决moment的痛点问题了。
1 不在添加新功能
2 不会讲API变为immutable
3 不会解决tree shaking 和宝体积的问题
4 不会进行任何重大修改(v3)
5 可能不会修复bug,特别是长期存在的已知问题
但是官方也推荐了兄弟库Day.js ,它被设计为了moment.js的缩减版本,它的api与moment极其类似,可以快读入门。