关于JavaScript中的Date类型,相信JSer们都不会陌生吧,但是也必然为那个复杂难记的各种转换函数所头疼,本文将分享一下我对JS中的Date类型的一些知识小总结,并把其中容易犯错的地方指出来,同时简介和推广moment.js这个js库,希望大家看完文章后以后在对Date类处理如鱼得水。
1 时间的唯一性与多样性
某一时刻在全世界任何地区应该是唯一的,时区的不同是为了让地球不同时区的人的中午十二点都是太阳正上当头,形成交流上没有那么多障碍。而这一标准就是大家熟知的格林威治标准时间(Greenwich Mean Time,又称世界时,简称GMT),GMT时间的准确度为每日数毫秒,对于这种情况,协调世界时(Coordinated Universal Time,简称UTC)出现了,准确度为每日数纳秒。UTC用1970
年1 月1 日午夜(零时)开始经过的毫秒数来保存日期。标准的出现并没有让我们的JavaScript对于时间处理变得简单,因为全世界时区的不同,所以你提供的是UTC时间还是本地时间对处理的结果很重要,同样的,结果显示UTC时间还是本地时间很多时候也相差了一个时区。
2 将已知信息转换为Date类
构造函数new Date()中传参
Date 构造函数而不传递参数的情况下,新创建的对象自动获得当前日期和时间。如果想根据特定的日期和时间创建日期对象,必须传入表示该日期的毫秒数(即从UTC 时间1970 年1 月1 日午夜起至该日期止经过的毫秒数)。所以new Date(0)即为UTC时间1970 年1 月1 日00:00:00.000,但是传入若为表示时间的字符串,则会自动调用传入ECMAScript
的Date.parse()方法将字符串转化成对应距离GMT标准时间的毫秒数,例如new Date("May 25, 2004")和new Date(Date.parse("May 25, 2004"))创建的是同一时刻的Date类。然而Date.parse()这个方法的行为因实现而异,而且通常是因地区而异,所以对于代码的跨域跨平台是一道隐患,不推荐使用。
如同模仿Date.parse()一样,Date 构造函数也会模仿Date.UTC(),Date.UTC()方法同样也返回表示日期的毫秒数,但它与Date.parse()在构建值时使用不同的信息。Date.UTC()的参数分别是年份、基于0 的月份(一月是0,二月是1,以此类推)、月中的哪一天(1
到31)、小时数(0 到23)、分钟、秒以及毫秒数。在这些参数中,只有前两个参数(年和月)是必需的。如果没有提供月中的天数,则假设天数为1;如果省略其他参数,则统统假设为0。以下是两个使用Date.UTC()方法的例子:
var y2k = new Date(Date.UTC(2000, 0)); // GMT 时间2000
年1 月1 日午夜零时
var allFives = new Date(Date.UTC(2005, 4, 5, 17, 55, 55)); //
GMT 时间2005 年5 月5 日17:55:55
但是,是不是new Date(Date.UTC(2005, 4, 5,
17, 55, 55))和new Date(2005, 4, 5, 17, 55, 55)创建的是同一时刻的Date类呢?答案是否定的!new Date()日期和时间都基于本地时区而非GMT 来创建的,也就是new Date(2005, 4, 5, 17, 55, 55)创建的是本地
时间2005 年5 月5 日17:55:55,若代码执行环境是中国(GMT+08),就对应的是创建GMT 时间2005 年5 月5 日09:55:55,所以很多时候我们会在这里犯错。
总结下来,new Date()构造函数传参方法很容易出错,而且对于字符串的支持格式还很有限,例如我得到的字符串是“12-10-27 09:00:00 PM”,我们要一步一步把它转换成可以放进new Date()里的字符串也是相当麻烦的过程,所以我推荐大家使用moment.js。
moment.js传参
其实moment.js是“冒充”继承了Date构造函数的一个类,所以上述new Date()的规则对它来说都是可以的。例如,上述的“12-10-27 09:00:00 PM",我们就可以用moment("12-10-27
09:00:00 PM", "YY-MM-DD hh-mm-ss A")就可以了。需要注意的是moment.js也无可避免的会出现上述的本地时间还是GMT时间的问题,如果没有在传参的字符串没有时区信息也会按本地时间去处理,所以只要注意这一点了,还是大大简化了我们的工作的。
3 将Date类转换成目标信息
原生Date类的方法已经足够去把一个Date类转换成各种信息,当然如果是用了上述moment.js生成的moment类,它的转换字符串format方法只会比原生的Date类方法有过之而无不及,这里就只是把原生方法介绍一下了。
· toString ------- (new Date()).toString()
------- "Sun Apr 24 2016 15:44:02 GMT+0800 (??-???? ?????—?é—′)" //输出信息因地区和浏览器变化
· toUTCString ------- (new Date()).toUTCString()
------- "Sun, 24 Apr 2016 07:42:41 GMT" // 输出信息格式恒定
· getTimezoneOffset() -------
返回本地时间与UTC时间相差的分钟数。例如,美国东部标准时间返回300。在某地进入夏令时
的情况下,这个值会有所变化
· getTime() ------- 返回表示日期的毫秒数;与valueOf()方法返回的值相同
· setTime(毫秒) ------- 以毫秒数设置日期,会改变整个日期
· getFullYear() ------- 取得4位数的年份(如2007而非仅07)
· getUTCFullYear() ------- 返回UTC日期的4位数年份
· setFullYear(年) ------- 设置日期的年份。传入的年份值必须是4位数字(如2007而非仅07)
· setUTCFullYear(年) ------- 设置UTC日期的年份。传入的年份值必须是4位数字(如2007而非仅07)
· getMonth() ------- 返回日期中的月份,其中0表示一月,11表示十二月
· getUTCMonth() ------- 返回UTC日期中的月份,其中0表示一月,11表示十二月
· setMonth(月) ------- 设置日期的月份。传入的月份值必须大于0,超过11则增加年份
· setUTCMonth(月) ------- 设置UTC日期的月份。传入的月份值必须大于0,超过11则增加年份
· getDate() ------- 返回日期月份中的天数(1到31)
· getUTCDate() ------- 返回UTC日期月份中的天数(1到31)
· setDate(日) ------- 设置日期月份中的天数。如果传入的值超过了该月中应有的天数,则增加月份
· setUTCDate(日) ------- 设置UTC日期月份中的天数。如果传入的值超过了该月中应有的天数,则增加月份
· getDay() ------- 返回日期中星期的星期几(其中0表示星期日,6表示星期六)
· getUTCDay() ------- 返回UTC日期中星期的星期几(其中0表示星期日,6表示星期六)
· getHours() ------- 返回日期中的小时数(0到23)
· getUTCHours() ------- 返回UTC日期中的小时数(0到23)
· setHours(时) ------- 设置日期中的小时数。传入的值超过了23则增加月份中的天数
· setUTCHours(时) ------- 设置UTC日期中的小时数。传入的值超过了23则增加月份中的天数
· getMinutes() ------- 返回日期中的分钟数(0到59)
· getUTCMinutes() ------- 返回UTC日期中的分钟数(0到59)
· setMinutes(分) ------- 设置日期中的分钟数。传入的值超过59则增加小时数
· setUTCMinutes(分) ------- 设置UTC日期中的分钟数。传入的值超过59则增加小时数
· getSeconds() ------- 返回日期中的秒数(0到59)
· getUTCSeconds() ------- 返回UTC日期中的秒数(0到59)
· setSeconds(秒)
------- 设置日期中的秒数。传入的值超过了59会增加分钟数
· setUTCSeconds(秒) ------- 设置UTC日期中的秒数。传入的值超过了59会增加分钟数
· getMilliseconds() ------- 返回日期中的毫秒数
· getUTCMilliseconds() ------- 返回UTC日期中的毫秒数
· setMilliseconds(毫秒) ------- 设置日期中的毫秒数
· setUTCMilliseconds(毫秒) ------- 设置UTC日期中的毫秒数