这篇文章的目的主要是讲解JavaScript
中的Date
对象,同时解答下面几个困惑我好久的问题:html
TimeZone
表示时间的词不少,好比时间
,日期
,时刻
等,为了便于下面的讲解以及概念的统一,对于下面这种格式浏览器
YYYY-MM-DDTHH:mm:ss.sssZ
如今统一约定:函数
YYYY-MM-DD
: 也就是年月日部分使用日期这个词;HH:mm:ss.sss
: 也就是时分秒部分使用时刻这个词;YYYY-MM-DDTHH:mm:ss.sssZ
: 也就是说并不特指日期和时刻时,咱们用时间这个词;其它名词约定:prototype
时间对象
:经过Date
构造函数建立的对象;内部插槽
:指官网文档中的internal slot
;计算机时区
:指计算机设置的时区,而不是计算机所在地区的时区;虽然JavaScript
用了Date
这个单词,这个单词翻译过来是日期
,可是从上面的约定来看,翻译成时间
这个词或许更为合适。翻译
至于为何采用上面这种字符串格式,而不是YYYY/MM/DD HH:mm:ss
或者其它格式进行说明的缘由下面会说起。code
另外,下面全部代码的运行环境为Chrome浏览器,而且注释部分不必定表明返回值。orm
文章将会从如下几个方面进行讲解:htm
Date
概述Date
做为构造器的用法;Date
做为函数的用法;Date
上的静态方法;getter
相关函数;setter
相关函数;经过把Date
做为构造函数使用,能够建立一个时间对象,这个时间对象表示时间长河中的一个时间点。时间对象内部有一个名为[[DateValue]]
的内部插槽,这个内部插槽里面存储的是一个时间戳
。这个时间戳表示的是以世界协调时的1970年1月1日0时0分0秒0毫秒做为起始的毫秒数。对象
问:不知道是否有人有过疑问,时间戳和时区相关吗,同一时间不一样时区获取的时间戳同样吗?
答:根据上面时间戳的规定,时间戳就是从世界协调时开始算的,因此能够说时间戳和时区有关,这个时区就是世界协调时。但也是由于这个时区是定死的,因此不一样的时区在同一时间获取到的时间戳都是同样的。ip
在JavaScript
中,咱们常常会经过参数的类型和个数让函数做出不一样的处理,如:
function justForExample () { // 这个例子只是起说明做用,并没有实际意义 let length = arguments.length if (length === 0) return 'zero parameter' if (length === 1) return arguments[0] if (length === 2) return arguments[0] + arguments[1] // 两个参数作加法 if (length === 3) return arguments[0] * arguments[1] * arguments[2] // 三个参数作乘法 // ... }
Date
也是经过判断参数的类型和个数来进行不一样处理的。Date
能够处理的参数的个数是0
到7
个。
当参数的个数是0
的时候,返回一个时间对象,[[DateValue]]
内部插槽的值表明以世界协调时为基准的当前时间的时间戳。
当参数的个数是1
的时候,还需根据参数的类型作进一步判断:
[[DateValue]]
内部插槽的值就是这个数字,固然若是这个数据不合法或者超出边界的话,这个插槽的值就不必定是这个数字了。未免本文过于啰嗦,本文不讨论数字不合法或者超出边界等其它状况,有兴趣的能够参阅规范文档。Date
上的静态方法parse
,而后把返回值做为[[DateValue]]
的值。具体详见下面的Date.parse
。当参数的个数大于2
的时候,就会使用下面这种形式:
// 从左到右参数分别表明年,月,日,时,分,秒,毫秒 Date (year, month [,date [, hours [, minutes [, seconds [, ms ]]]]])
上面这种形式接受2
到7
个参数。日的默认值是1
,时,分,秒,毫秒的默认值是0
。
须要注意的是:
0
开始算的,也就是0
表明1月
,1
表明2月
...11
表明12月
。我在文章的开始说过一个进位
的问题。咱们知道当两个十进制的数相加时,若是低位超出该位的最大值,那么就会向高位进位,以使该位的值在合法范围以内。一样,在Date
构造器以上述形式调用的时候,就会发生自动进位,也就是若是该位的值已经超出了该位的最大值,并不会报错,而是自动执行进位操做:
// 进位 new Date(2018, 8, 34) // Thu Oct 04 2018 00:00:00 GMT+0800 (中国标准时间) // 退位,相似于数学中的减法,也是能够的 new Date(2018, 8, -1) // Thu Aug 30 2018 00:00:00 GMT+0800 (中国标准时间)
能够看到,第三个参数34
表示月份中的天数,可是9
月只有30
天,因此34
并非9
月合法的日期,因此就产生了进位,月份进入10
月,而后日期是4
日,也就是34-30
。同理,当第三个参数是-1
的时候,会退到8
月份。
时区是计算机时区
。也就是年,月,日,时,分,秒,毫秒表明的是计算机时区的时间。所以,不一样的计算机返回的时间多是不同的:
let date1 = new Date(2018, 8, 8, 8, 8, 8) // Sat Sep 08 2018 08:08:08 GMT+0800 (中国标准时间) date1.getTime() // 1536365288000 // 而后,改了下计算机时区 let date2 = new Date(2018, 8, 8, 8, 8, 8) // Sat Sep 08 2018 08:08:08 GMT+0300 (莫斯科标准时间) date2.getTime() // 1536383288000 (date1 - date2) / 3600 / 1000 // 5,由于date1是东八区,date2是东三区,正好相差5个小时
当Date
做为普通函数调用时,并不会对参数进行处理,直接返回表明当前时间的字符串。
Date() // "Sat Aug 18 2018 17:26:16 GMT+0800 (中国标准时间)" Date(2018, 9, 9) // "Sat Aug 18 2018 17:26:21 GMT+0800 (中国标准时间)"
Date
上的静态方法有三个:
返回函数调用时,以世界协调时为基准的时间戳。
Date.parse
处理第一个参数,返回一个以世界协调时为基准的时间戳。
在上面介绍Date
做为构造函数使用的时候,当参数的个数是1
,而且类型是字符串时,会在内部调用Date.parse
方法。
咱们平时见过不少表示时间的格式:
"2018-08-08 08:08:08" "2018/08/08 08:08:08" "2018/8/8 8:8:8" ...
那么,JavaScript
支持的格式有哪些?JavaScript
是否支持上述所有格式呢?
根据文档,规范只定义了一种格式:YYYY-MM-DDTHH:mm:ss.sssZ
,其中T
表明时间的开始,Z
表明时区,也就是世界协调时。时区还能够用+
或者-
拼上HH:mm
来表示。这也是我为何在开头使用这种格式的缘由。当字符串的格式不符合上述格式的时候,就交给具体的实现本身看着办了。
须要注意的是:
另外上述格式不是全部部分都有才算合法,能够省略某些部分,日期部分容许的格式以下:
YYYY YYYY-MM YYYY-MM-DD
时刻部分容许的格式以下:
THH:mm THH:mm:ss THH:mm:ss.sss
能够只使用上面的日期格式,也可使用上面的任意一种日期格式+上面的任意一种时刻格式。月、日的默认值是"01"
,时、分、秒的默认值是"00"
,毫秒的默认值是"000"
。时区缺省的时候,日期+时刻的格式表明的是计算机时区。
// 只有日期格式 new Date('2018-08-08') // Wed Aug 08 2018 08:00:00 GMT+0800 (中国标准时间) // 日期+时刻格式,时区默认是计算机时区 new Date('2018-08-08 08:08:08') // Wed Aug 08 2018 08:08:08 GMT+0800 (中国标准时间) // 时区为东三区,个人电脑是在东八区,因此输出的时间是08+05,也就是13点 new Date('2018-08-08 08:08:08+03:00') // Wed Aug 08 2018 13:08:08 GMT+0800 (中国标准时间)
上面第一个例子,能够发现当只有日期格式的时候,字符串是按照世界协调时解析的,也就是世界协调时的2018年8月8日,因此东八区就变成了8点了。文档只规定了日期+时刻格式默认时区是计算机时区,只有日期的时候并无规定用什么时区,因此尽可能不要用日期格式。
因此,就我的而言,我以为应该尽可能避免使用字符串格式来实例化一个时间对象。当想建立一个本地时区的时间对象时,可使用上面Date
做为构造函数接受2
到7
个参数的那种形式去实例化一个时间对象。
没有进位问题,相应部分超出合法值以外就会报错:
new Date('2018-08-34') // Invalid Date
相似于上面Date
做为构造函数时,使用2
到7
个参数的形式。不一样之处在于:
因此,能够经过下述方式建立参数以计算机时区和世界协调时为基准的时间对象:
// 参数是以计算机时区为基准 new Date(2018, 8, 8) // Sat Sep 08 2018 00:00:00 GMT+0800 (中国标准时间) // 参数是以世界协调时为基准 new Date(Date.UTC(2018, 8, 8)) // Sat Sep 08 2018 08:00:00 GMT+0800 (中国标准时间)
获取一个时间对象的年、月、日、时、分、秒、毫秒等都有对应的方法,这里再也不赘述,只简述几个注意点:
上述方法针对计算机时区和世界协调时都有对应的一系列方法,如获取小时:
// Date.prototype.getHours() 计算机时区 // Date.prototype.getUTCHours() 世界协调时 let date = new Date(2018, 8, 8, 8) //Sat Sep 08 2018 08:00:00 GMT+0800 (中国标准时间) date.getHours() // 8 date.getUTCHours() // 0
Date.prototype.getTime()
返回时间对象的内部插槽[[DateValue]]
的值,也就是以世界协调时为基准的时间戳。同getter相关函数同样,设置一个时间对象的年、月、日、时、分、秒、毫秒等都有对应的方法,这里一样再也不赘述。只简述几个注意点:
同getter相关函数同样,上述方法针对计算机时区和世界协调时都有对应的一系列方法,如设置日期:
// Date.prototype.setHours() 计算机时区 // Date.prototype.setUTCHours() 世界协调时 let date = new Date(2018, 8, 8, 8) //Sat Sep 08 2018 08:00:00 GMT+0800 (中国标准时间) date.setHours(9) // Sat Sep 08 2018 09:00:00 GMT+0800 (中国标准时间) date.setUTCHours(9) // Sat Sep 08 2018 17:00:00 GMT+0800 (中国标准时间)
设置月、日、时、分、秒、毫秒的时候,一样会有进位:
let date = new Date(2018, 8, 8) // Sat Sep 08 2018 00:00:00 GMT+0800 (中国标准时间) date.setDate(34) // Thu Oct 04 2018 00:00:00 GMT+0800 (中国标准时间)
但愿上述内容对你们有所帮助。若是发现本文有什么错误,您能够在评论区留言。