Moment.js 详细教程1
前言
在很多时候,我们需要对时间进行处理,比如时间间隔计算,时间转换,时间格式化等操作,如果用原生的JS进行操作的话,会是一件很繁琐的事情,幸好我们有了Moment.js使得时间的处理变得更加简单高效。
Moment.js简介
Moment.js 是一个 JavaScript 日期处理类库,用于解析、检验、操作、以及显示日期,Github地址为https://github.com/moment/moment/
官方文档地址为:http://momentjs.com/
安装
Nodejs中安装:
npm install moment
var moment = require('moment');
moment().format();
浏览器中安装:
<script src="moment.js"></script>
<script>
    moment().format();
</script>
解析
1.解析当前时间:
moment(new Date())
moment();
// 2.14.0 后还支持下面的方法
moment([]);
moment({});
创建后会返回这样一个对象:
Moment {_isAMomentObject: true, _isUTC: false, _pf: {…}, _locale: Locale, _d: Thu Jun 28 2018 14:36:22 GMT+0800 (中国标准时间), …}
2.传入字符串解析时间:
moment("12/25/1995", "MM-DD-YYYY");
它支持以下这些标识符:
年、月、日,标识符
| 输入 | 示例 | 说明 | 
|---|---|---|
| YYYY | 2014 | 4或2位年 | 
| YY | 14 | 2位年r | 
| Q | 1..4 | 季度。设置每季度的第一个月 | 
| M MM | 1..12 | 表示月的数字 | 
| MMM MMMM | Jan..December | 月份名 | 
| D DD | 1..31 | 每月的第几天 | 
| Do | 1st..31st | 每月的第几天的序数 | 
| DDD DDDD | 1..365 | 每年的第几天 | 
| X | 1410715640.579 | Unix时间戳 | 
| x | 1410715640579 | Unix时间戳(毫秒级) | 
周年、周、周日,标识符
| 输入 | 示例 | 说明 | 
|---|---|---|
| gggg | 2014 | 本地 4位周年 | 
| gg | 14 | 本地 2位周年 | 
| w ww | 1..53 | 本地 年中第几周 | 
| e | 1..7 | 本地 一周中的第几天 | 
| ddd dddd | Mon...Sunday | 本地星期名 | 
| GGGG | 2014 | ISO 4位周年 | 
| GG | 14 | ISO 2位周年 | 
| W WW | 1..53 | ISO 年中第几周 | 
| E | 1..7 | ISO 一周中的第几天 | 
时、分、秒、毫秒、时差,标识符
| 输入 | 示例 | 说明 | 
|---|---|---|
| H HH | 0..23 | 24 小时制 时 | 
| h hh | 1..12 | 12 小时制 时a A. | 
| a A | am pm | 上午和下午 | 
| m mm | 0..59 | 分 | 
| s ss | 0..59 | 秒 | 
| S | 0..9 | 十分之一秒 | 
| SS | 0..99 | 百分之一秒 | 
| SSS | 0..999 | 千分之一秒(毫秒) | 
| SSSS | 0000..9999 | 微秒 | 
| Z ZZ | +12:00 | 与UTC时间的时差,用+-HH:mm、+-HHmm或Z表示 | 
如果不确定需要哪种格式化,可以传入一个数组:
moment("12-25-1995", ["MM-DD-YYYY", "YYYY-MM-DD"]);
Moment.js会自动选择匹配的格式化格式。
3.使用对象解析:
moment({ hour:15, minute:10 });
moment({ y    :2010, M     :3, d   :5, h    :15, m      :10, s      :3, ms          :123});
moment({ year :2010, month :3, day :5, hour :15, minute :10, second :3, millisecond :123});
moment({ years:2010, months:3, days:5, hours:15, minutes:10, seconds:3, milliseconds:123});
moment({ years:2010, months:3, date:5, hours:15, minutes:10, seconds:3, milliseconds:123});
4.使用Unix 偏移量(毫秒)或者Unix 时间戳(秒)进行初始化
moment(1318781876406);
moment.unix(1318781876);
5.使用JSDate对象进行初始化
var day = new Date(2011, 9, 16);
moment(day);
6.使用数组
[year, month, day, hour, minute, second, millisecond]
moment([2010, 1, 14, 15, 25, 50, 125]); // February 14th, 3:25:50.125 PM
7.Moment对象复制
var a = moment([2012]);
var b = moment(a);
//或者
var b = a.clone();
8.UTC
moment.utc();
moment.utc(Number);
moment.utc(Number[]);
moment.utc(String);
moment.utc(String, String);
moment.utc(String, String[]);
moment.utc(String, String, String);
moment.utc(Moment);
moment.utc(Date);
默认情况下,Moment使用本地时间进行转换和显示。如果要使用UTC标准时间进行转换和显示,需要使用moment.utc()方法代替moment()。这就是Moment.js的UTC模式。
utc()方法只会在显示上使用UTC时间,二者本质上还是相同的时间
在UTC模式下,所有显示时间的方法都会使用UTC时间代替本地时间。
var a = moment();
var b = moment.utc();
a.format();  // 2013-02-04T10:35:24-08:00
b.format();  // 2013-02-04T18:35:24+00:00
a.valueOf(); // 1360002924000
b.valueOf(); // 1360002924000
9.转换时区
moment.parseZone("2013-01-01T00:00:00-13:00").utcOffset(); // -780 ("-13:00" in total minutes)
moment.parseZone('2013 01 01 05 -13:00', 'YYYY MM DD HH ZZ').utcOffset(); // -780  ("-13:00" in total minutes)
moment.parseZone('2013-01-01-13:00', ['DD MM YYYY ZZ', 'YYYY MM DD ZZ']).utcOffset(); // -780  ("-13:00" in total minutes);
10.验证
你可以使用moment.isValid方法检测输入的初始化时间是否合法,该方法会返回一个表示是否有效的布尔值。如果想查看转换详细结果,可以使用moment.parsingFlags方法,该方法会返回一个包含以下值的对象:
overflow:是否有溢出,如:13th月、月中的第32天invalidMonth:是否有效的月名empty:转入的字符串是否不可转换,如:输入moment('this is nonsense');则为truenullInput:是否输入了空值invalidFormat:是否无效的输入格式userInvalidated:是否创建成功,相当于moment.invalid()
当转换失败时,可以调用moment#invalidAt方法,查看失败位置:
var m = moment("2011-10-10T10:20:90");
m.isValid(); // false
m.invalidAt(); // 5 表示秒出错
返回值含义如下:
- 0年
 - 1月
 - 2天
 - 3时
 - 4分
 - 5秒
 - 6毫秒
 
11.查看创建的数据
你可以使用moment().creationData();获取到创建该时间对象的输入:
moment("2013-01-02", "YYYY-MM-DD", true).creationData()
//返回下面的对象
{
    input: "2013-01-02",
    format: "YYYY-MM-DD",
    locale: Locale obj,
    isUTC: false,
    strict: true
}
12.使用默认值
创建Moment时,可以只指定一些时间单位,其它的会使用当前时间的日、时、分、秒等。
moment();  // 当前时刻
moment(5, "HH");  // 今天, 5:00:00.000
moment({hour: 5});  // 今天, 5:00:00.000
moment({hour: 5, minute: 10});  // 今天, 5:10.00.000
moment({hour: 5, minute: 10, seconds: 20});  // 今天, 5:10.20.000
moment({hour: 5, minute: 10, seconds: 20, milliseconds: 300});  // 今天, 5:10.20.300
moment(5, "DD");  // 本月的第5天
moment("4 05:06:07", "DD hh:mm:ss");  // 本月的第4天, 05:06:07.000
moment(3, "MM");  // 今年的第4个月 (April)
moment("Apr 4 05:06:07", "MMM DD hh:mm:ss");  // 今年4月的第5天, 05:06:07.000
设置与取值
Moment.js使用了重载的getter和setters,当有值的时候是一个setters,表示设置时间的对应的分,秒或日期等,当没有值传入的时候是一个getter,返回对应的时间的分或者秒等:
moment().millisecond();  //毫秒
moment().second(); //秒
moment().minute();//分
moment().hour();//小时
moment().date();//日期
moment().day(); //星期
moment().day(7); //上星期日
moment().day(-7);//下星期日
moment().weekday(); 本地化星期
//当周一为星期的第一天时
moment().weekday(-7); // 上周一
moment().weekday(7); // 下周一
//当周日为星期的第一天时
moment().weekday(-7); // 上周日
moment().weekday(7); // 下周日
moment().isoWeekday(); // ISO星期 
moment().isoWeekday(1); // 周一
moment().isoWeekday(7); // 周日
moment().dayOfYear(); //一年中的第几天
moment().weeks(); //一年中的第几周
moment().isoWeek(); //ISO周
moment().months(); //月份0-11
moment().quarter();  //季度1-4
moment().year(); //年 -270,000 〜 270,000
moment().weekYear(); //本地化的 周-年
moment().isoWeekYear();//ISO周、年
moment().weeksInYear(); //本地化时间的周数
moment().isoWeeksInYear(); //ISO 周数
或者你也可以直接使用.get(str,value)或者.set(str)加上上面提到的那些属性来设置或取值:
moment().get('year');
moment().set('year', 2013);
你还可以来取最大值或最小值:
moment.max(Moment[,Moment...]);
moment.min(Moment[,Moment...]);
var a = moment().subtract(1, 'day');
var b = moment().add(1, 'day');
moment.max(a, b);  // b
moment.min(a, b);  // a
时间操作
Moment.js的时间操作支持链式调用:
moment().add(7, 'days').subtract(1, 'months').year(2009).hours(0).minutes(0).seconds(0);
1.时间增加或减少
语法如下:
moment().add(Number, String);
moment().add(Duration);
moment().add(Object);
moment().subtract(Number, String);
moment().subtract(Duration);
moment().subtract(Object);
第二个参数为单位字符串形式,可以使用全拼或者简写形式,简写对应关系如下:
单位	简写
years	y
quarters	Q
months	M
weeks	w
days	d
hours	h
minutes	m
seconds	s
milliseconds	ms
当增加月后,如果目标月的天数超过出最大值,将变为目标月的最后一天
如果传递小数的话,则会自动转换为最接近的整数
moment().add(7, 'days').add(1, 'months');
moment().subtract(7, 'days');
moment().subtract(1, 'seconds');
moment().add({days:7,months:1});
var duration = moment.duration({'days' : 1});
moment([2012, 0, 31]).add(duration); // February 1
moment().add(1.5, 'months') == moment().add(2, 'months')
moment().add(.7, 'years') == moment().add(8, 'months') //.7*12 = 8.4, rounded to 8
2.开始时间 (Start of Time)与结束时间(End of Time)
moment().startOf(String);
moment().endOf(String);
moment().startOf('year');    // 设置为今年1月第一天的 12:00 am
moment().startOf('month');   // 设置为本月第一天的 12:00 am
moment().startOf('quarter');  // 设置为本季度第一个月第一天的 12:00 am
moment().startOf('week');    // 设置为本周第一天的 12:00 am
moment().startOf('isoWeek'); // 设置为ISO本周的第一天的 12:00 am
moment().startOf('day');     // 设置为今天的 12:00
moment().startOf('hour');    // 设置为当前时间的小时,0分0秒0毫秒
moment().startOf('minute');  // 设置为当前的时间的分钟,according
moment().startOf('second');  // 类似 moment().milliseconds(0);
moment().endOf("year"); // 设置为今年的 12-31 11:59:59.999 pm
3.最大值与最小值
moment().max(Moment|String|Number|Date|Array);
moment().min(Moment|String|Number|Date|Array);
将当前moment时间设置为和另一个moment时间相比较大或较小的一个,a.max(b)与a = moment.min(a, b)相同,a.min(b)与a = moment.max(a, b)相同。
4.本地化与UTC
moment().local();
moment().utc();
5.UTC 偏移量(UTC Offset)
moment().utcOffset(); //获取偏移量
moment().utcOffset(Number|String); //设置偏移量
一般设置偏移量都会默认是分钟数,当输入小于16且大于-16时,moment会理解为输入的是小时:
moment().utcOffset(8);  // 设置小时偏移量
moment().utcOffset(480);  // 设置分钟偏移量 (8 * 60)
也可以通过字符串形式进行设置:
moment().utcOffset("+08:00");
moment().utcOffset(8);
moment().utcOffset(480);
当通过字符串进行设置时,moment().utcOffset会首先匹配+00:00 +0000 -00:00 -0000,即使你输入了ISO 8601格式的字符串,moment也会将成变成这个UTC 偏移量。
输入的字符串要以+和-的形式开头,如果不以这种形式开头会被解释为"+00:00"。
moment().utcOffset("2013-03-07T07:00:00+08:00");
6.时区偏移量(Timezone Offset)
moment().zone();//获取偏移量
moment().zone(Number|String);//设置偏移量
设置偏移量同UTC偏移量,可以输入数字或者是字符串,且小于16大于-16会理解为小时
格式化显示
1.格式化
moment().format();
moment().format(String);
它支持下列标识符
| 标识 | 输出 | |
|---|---|---|
| 月 | M | 1 2 ... 11 12 | 
| Mo | 1st 2nd ... 11th 12th | |
| MM | 01 02 ... 11 12 | |
| MMM | Jan Feb ... Nov Dec | |
| MMMM | January February ... November December | |
| 季 | Q | 1 2 3 4 | 
| 天数(月) | D | 1 2 ... 30 31 | 
| Do | 1st 2nd ... 30th 31st | |
| DD | 01 02 ... 30 31 | |
| 天数(年) | DDD | 1 2 ... 364 365 | 
| DDDo | 1st 2nd ... 364th 365th | |
| DDDD | 001 002 ... 364 365 | |
| Day of Week | d | 0 1 ... 5 6 | 
| do | 0th 1st ... 5th 6th | |
| dd | Su Mo ... Fr Sa | |
| ddd | Sun Mon ... Fri Sat | |
| dddd | Sunday Monday ... Friday Saturday | |
| 星期(本地) | e | 0 1 ... 5 6 | 
| 星期(ISO) | E | 1 2 ... 6 7 | 
| 周数 | w | 1 2 ... 52 53 | 
| wo | 1st 2nd ... 52nd 53rd | |
| ww | 01 02 ... 52 53 | |
| 周数(ISO) | W | 1 2 ... 52 53 | 
| Wo | 1st 2nd ... 52nd 53rd | |
| WW | 01 02 ... 52 53 | |
| 年 | YY | 70 71 ... 29 30 | 
| YYYY | 1970 1971 ... 2029 2030 | |
| 周、年 | gg | 70 71 ... 29 30 | 
| gggg | 1970 1971 ... 2029 2030 | |
| 周、年(ISO) | GG | 70 71 ... 29 30 | 
| GGGG | 1970 1971 ... 2029 2030 | |
| AM/PM | A | AM PM | 
| a | am pm | |
| 时 | H | 0 1 ... 22 23 | 
| HH | 00 01 ... 22 23 | |
| h | 1 2 ... 11 12 | |
| hh | 01 02 ... 11 12 | |
| 分 | m | 0 1 ... 58 59 | 
| mm | 00 01 ... 58 59 | |
| 秒 | s | 0 1 ... 58 59 | 
| ss | 00 01 ... 58 59 | |
| 分数秒 | S | 0 1 ... 8 9 | 
| SS | 00 01 ... 98 99 | |
| SSS | 000 001 ... 998 999 | |
| SSSS ... SSSSSSSSS | 000[0..] 001[0..] ... 998[0..] 999[0..] | |
| 时区 | z or zz | 
				EST CST ... MST PST  注意: 自 1.6.0版本后, z/zz格式标识不再支持 查看详细 
			 | 
		
| Z | -07:00 -06:00 ... +06:00 +07:00 | |
| ZZ | -0700 -0600 ... +0600 +0700 | |
| UNIX时间戳(秒级) | X | 1360013296 | 
| NIX时间戳(毫秒级) | x | 1360013296123 | 
因为不同地区的首选格式不同,这里还提供了一些特殊标识时用于moment的本地格式化。在这些格式中,格式标识大小写作用相同:
| 时间 | LT | 8:30 PM | 
| 时间和秒 | LTS | 8:30:25 PM | 
| 数字月、日、年 | L | 09/04/1986 | 
| l | 9/4/1986 | |
| 月名、日、年 | LL | September 4 1986 | 
| ll | Sep 4 1986 | |
| 月名、日、年、时间 | LLL | September 4 1986 8:30 PM | 
| lll | Sep 4 1986 8:30 PM | |
| 月名、日、星期、年、时间/b> | LLLL | Thursday, September 4 1986 8:30 PM | 
| llll | Thu, Sep 4 1986 8:30 PM | 
在格式化字符串,如果包括转义字符,可以将其用方括号包起来:
moment().format('[today] dddd'); // 'today Sunday'
2.时差 (之前,相对于当前时间)
moment().fromNow();
moment().fromNow(Boolean);
如果设置为true,会得到一个不含后缀的值:
moment([2007, 0, 29]).fromNow(); // "11 years ago"
moment([2007, 0, 29]).fromNow(true); // "11 years"
下面是一些用于输出时间范围的标识字符:
| 范围 | 标识 | 输出 | 
|---|---|---|
| 0 - 45 秒 | s | a few seconds ago | 
| 45 - 90 秒 | m | a minute ago | 
| 90 秒 - 45 分 | mm | 2 minutes ago ... 45 minutes ago | 
| 45 - 90 分 | h | an hour ago | 
| 90 分 22 小时 | hh | 2 hours ago ... 22 hours ago | 
| 22 - 36 小时 | d | a day ago | 
| 36 小时 - 25 天 | dd | 2 days ago ... 25 days ago | 
| 25 - 45 天 | M | a month ago | 
| 45- 345 天 | MM | 2 months ago ... 11 months ago | 
| 345 - 545 天 (1.5 年) | y | a year ago | 
| 546 天+ | yy | 2 years ago ... 20 years ago | 
4.时差 (之前,相对于给定的时间)
moment().from(Moment|String|Number|Date|Array);
moment().from(Moment|String|Number|Date|Array, Boolean);
5.时差 (之后,相对于现在时间)
moment().toNow();
moment().toNow(Boolean);
moment([2007, 0, 29]).toNow();     //"in 11 years"
moment([2007, 0, 29]).toNow(true); // "11 years"
下面是一些用于输出时间范围的标识字符:
| 范围 | 标识 | 输出 | 
|---|---|---|
| 0 - 45 秒 | s | in seconds | 
| 45 - 90 秒 | m | in a minute | 
| 90 秒 分 45 秒 | mm | in 2 minutes ... in 45 minutes | 
| 45 - 90 分 | h | in an hour | 
| 90 分 - 22 小时 | hh | in 2 hours ... in 22 hours | 
| 22 - 36 小时 | d | in a day | 
| 36 小时 - 25 天 | dd | in 2 days ... in 25 days | 
| 25 - 45 天 | M | in a month | 
| 45 - 345 天 | MM | in 2 months ... in 11 months | 
| 345 - 547 天 (1.5 年) | y in a year | |
| 548 天+ | yy | in 2 years ... in 20 years | 
6.时差 (之后,相对于给定的时间)
moment().to(Moment|String|Number|Date|Array);
moment().to(Moment|String|Number|Date|Array, Boolean);
7.日历时间
moment().calendar();
moment().calendar(referenceTime);
moment().calendar(referenceTime, formats);  // from 2.10.5
日历时间用于显示参考时间referenceTime(默认为现在时间),但不与moment().fromNow()有所有不同。
moment().calendar()会用跟据传入字符串的不同按不同的格式输出。
moment().calendar(); //"Today at 4:37 PM"
8.时差 (毫秒)
moment().diff(Moment|String|Number|Date|Array);
moment().diff(Moment|String|Number|Date|Array, String);
moment().diff(Moment|String|Number|Date|Array, String, Boolean);
获取一个毫秒级的时差,moment().diff()方法类似于moment().from()方法。
var a = moment([2007, 0, 29]);
var b = moment([2007, 0, 28]);
a.diff(b) // 86400000
如果需要获取其它单位的时间,可以在调用方法时传入第二个参数,传入第三个参数可以获得浮点数:
var a = moment([2008, 9]);
var b = moment([2007, 0]);
a.diff(b, 'years');       // 1
a.diff(b, 'years', true); // 1.75
9.Unix 偏移量 (毫秒) 和 Unix 时间戳 (秒)
moment().valueOf(); //偏移量
+moment(); //偏移量
moment().unix();//时间戳
10.获取当月天数
moment().daysInMonth();
11.获取JavaScript Date对象
moment().toDate();
通过Moment.js获取一个JavaScript Date对象,使用moment().toDate()方法。
将要返回的Date是moment正在使用的对象,所以任何对Date的修改也会导致moment改变。如果你只想获取一个Date副本,应该在调用moment().toDate()方法前使用moment().clone()方法。
12.转换为数组
moment().toArray(); //[2018, 5, 28, 16, 47, 37, 948]
13.转换为JSON
moment().toJSON(); //"2018-06-28T08:47:51.955Z"
14.转换为ISO 8601 字符串
moment().toISOString();
moment().toISOString(keepOffset); // from 2.20.0
15.转换为Object
moment().toObject();
16.转换为字符串
moment().toString();
17.检测
moment().inspect(); //"moment("2018-06-28T16:53:13.184")"
返回一个机器可读的字符串,更多用来debug使用
查询
moment().isBefore(Moment|String|Number|Date|Array);//是否之前
moment().isBefore(Moment|String|Number|Date|Array, String);
moment().isSame(Moment|String|Number|Date|Array);//是否相同
moment().isSame(Moment|String|Number|Date|Array, String);
moment().isAfter(Moment|String|Number|Date|Array);//是否之后
moment().isAfter(Moment|String|Number|Date|Array, String);
moment().isSameOrBefore(Moment|String|Number|Date|Array);
moment().isSameOrBefore(Moment|String|Number|Date|Array, String);
moment().isSameOrAfter(Moment|String|Number|Date|Array);
moment().isSameOrAfter(Moment|String|Number|Date|Array, String);
//From 2.13.0 onward
moment().isBetween(moment-like, moment-like);//是否之间
moment().isBetween(moment-like, moment-like, String);
moment().isBetween(moment-like, moment-like, String, String);
//2.9.0 to 2.12.0
moment().isBetween(moment-like, moment-like);//是否之间
moment().isBetween(moment-like, moment-like, String);
moment().isDST();//是否夏令时
moment('2013-03-10 2:30', 'YYYY-MM-DD HH:mm').isDSTShifted()//是否被转换的夏令时
moment().isLeapYear(); //是否闰年
moment.isMoment(obj);//是否Moment对象
moment.isDate(obj);//是否Date对象
isBefore或isSame或isAfter,isSameOrBefore,isSameOrAfter的第二个参数和isBetween的第三个参数是时间比较级别,不设置的时候默认比较级别是毫秒级别,设置后会比较当前级别和及其以上级别单位。
isBetween的第四个参数,可以设置左右包含情况,[]表示包含,()表示不包含。
moment('2016-10-30').isBetween('2016-10-30', '2016-12-30', null, '()'); //false
moment('2016-10-30').isBetween('2016-10-30', '2016-12-30', null, '[)'); //true
moment('2016-10-30').isBetween('2016-01-01', '2016-10-30', null, '()'); //false
moment('2016-10-30').isBetween('2016-01-01', '2016-10-30', null, '(]'); //true
moment('2016-10-30').isBetween('2016-10-30', '2016-10-30', null, '[]'); //true
更多精彩请看下一篇:Moment.js 详细教程2