这篇断断续续写了很久,是因为时间这个坑真的可以越挖越深,本来名字叫“关于时间戳的一切”,打算总结几种时间格式到时间戳的转换方法,结果越总结发现自己自己不懂的越多,后续还会再补充的。这次关于时间的探索让我重新学了Date对象、Unix时间戳、时间的几种标准、还重学了地理等。
---------------最后看下面这块------------
遇到两个问题,js中使用new Date()取出的时间结果会因为输入时间精度、格式不同而不同:在精度无时分秒YYYY-MM-DD和有时分秒YYYY-MM-DD hh:mm:ss 之后使用getTime取到的时间戳不同,多出8小时;以及在YYYY-MM-DD和YYYY/MM/DD返回的结果不同,也是差8小时。如图:
从测试结果来看:
new Date('1970-01-01')和new Date('1970-01-01 08:00:00')的getTime()结果相同,我有点懵b;
继续看new Date('1970/01/01')和new Date('1970-01-01') ,输出结果后者多了8小时;
emmm...瞬间感到很可怕,一直以为'1970-01-01'等于'1970-01-01 00:00:00' 、'1970-01-01''等于1970/01/01'的我,会不会过去的代码中制造了什么错误..
仔细对比分析有了两个推测:
1,new Date('/') 接收的是当地时间,没写时分秒自动补0,输入与输出一致
2,new Date('-') 接收的是UTC时间,没写时分秒自动补0,输出本地时间;写了时分秒也就是YYYY-MM-DD hh:mm:ss格式时接收的是当地时间,输入与输出一致
---------------------最后看上面这块-----------------------
一、时间戳和时区
1,Unix时间戳(Unix timestamp)定义为从1970年01月01日00时00分00秒(UTC)起至现在经过的总秒数。
2,JavaScript中提供的Date对象可以将所有时间都存为一个整数,表示从1970年1月1日00:00:00起的总毫秒数。
↑这两点意味着:
1)使用unix时间戳作为参数需要乘以1000得到毫秒数Date()对象才能正确接收,getTime时需要除以1000才能得到时间戳。
2)js中判断一个时间戳的精度,可以靠时间戳长度:精确到秒是10位;精确到毫秒是13位。
3)在js中利用时间戳很容易计算出一个间隔恒定的时间轴,或者给一个时间推算出某段时间之前or之后的具体日期,或者日期比较
3,北京时间 = GMT+8 = UTC+8
GMT是格林尼治平均时,UTC是世界标准时/协调世界时/原子时。前者是太阳时,GMT的正午为太阳在格林尼治上空最高点的时间,但是这个时间受地球自转速度影响所以每一天的时间都存在一定误差;后者由原子能级跃迁振动频率计时得出误差很小。GMT几乎等于UTC。北京时间采用东八区时间,复习一下地理:本初子午线是0度经线穿过格林尼治天文台,日期变更线基于东西经重合的180度经线。全球24个时区里,我们在东经120度落在东八区,由于地球自西向东旋转我们要比英国的盆友更早迎接新的一天的早中晚,时间上就是早了8个小时。当英国时间为正午时,我们的时间为晚上8点,这时全球都在同一天。
↑这意味着:
Unix时间戳起始时间是我们北京时间的1970年01月01日08时00分00秒
二、几种表示时间的格式/标准
1,RFC-2822标准格式,形如:
Sun Apr 08 2018 11:38:39 GMT+0800(CST)
2,ISO-8601标准格式,其中一种常见的格式形如:
2018-04-08T11:38:39+08:00 日期用“-”相隔,与时间用“T”连接
2018-04-08T11:38:39Z Z代表UTC时间,Z也可写成00:00
三、js中的Date对象
1,Date()作为函数不管有无参数直接调用获取的是当前的日期和时间,结果是表示当前时间的字符串,并且是已经转换为当前时区的时间;
2,Date()作为构造函数无参数时使用new Date(),结果是表示当前时间的对象,并且是已经转换为当前时区的时间
GMT+0800(CST)代表东八区,CST(china standard time)表示中国标准时间
3,作为构造函数时,Date对象可以接收多种格式的参数,用法如下:
new Date() //返回当前时间
new Date(number) //number为自1970.01.01 00:00:00经过的毫秒数,返回number毫秒后的时间
new Date(string) //string代表时间的字符串,返回这个时间的Date对象
new Date(year, month, day, hours, minutes, seconds, milliseconds)
构造出的日期用来显示时会转为本地时间(toString方法)
当参数为string时,写法很多,所有能被Date.parse()解析的字符串都可以作为参数。需要注意的是,es5中,当日期以“-”作为分隔符且月日数字小于10前面补0(如2018-09-03),和数字大于9(如2018-10-10),JavaScript接收时会把字符串当作ISO-8601格式按照0时区也就是UTC时间来接收;es6改为没有指定时区就会默认为当地时间。其他格式如2018/10/10都是非ISO-8601格式接收当作本地时间。'2018-04-08T00:00:00Z'是UTC,'2018-04-08 00:00:00'非UTC等于ISO-8601格式的'2018-04-08T00:00:00+08:00'。
↑这也就解释了开篇的疑惑,推测基本正确,只是有“-”不一定是UTC,而且推测的时候对于GMT和UTC没有做精确区分。真正原因上面这段。
4,日期的运算
两个日期对象相减,得到相差的毫秒数;相加为两个日期字符串的相加。
↑这意味着算时间差时无需先getTime,可以直接相减。
5,计算1970-01-01 00:00:00至指定日期的毫秒数
1)new Date('日期').getTime()
2) Date.parse('日期')
3)Date.UTC('日期') 该日期为UTC时间,不会根据写法不同做本地转换
4)Date.now() 至当前时间,可用来计算代码运行时间
5) +new Date('日期') 等于 new Date('日期').getTime()
四、几种标准的时间与时间戳的转换(js中时间戳的N种获取方式)
1, js获取某一时间的时间戳上面第三点第5标题下的任意一种方法获取1970-01-01 00:00:00至指定日期的毫秒数 为ms,
Math.round(ms/1000)
如果是当前时间直接除以1000也可以Math.round(new Date() / 1000)
2,时间戳转时间字符串
1)转“2018-04-08”或“2018/04/08”或任意组装的格式
先用new Date(UnixTimeStamp)将时间戳转为Date类型对象,再使用getFullYear(),getMonth(),getDate(),getHours(),getMinutes(),getSeconds()分别获取年月日时分秒,注意的是getMonth()返回数字是0~11,所以换成可读的月份要加1。
2)转ISO-8061格式的UTC时间和本地易读的时间
toJSON(),toISOString(),toLocaleString()如图
3)转RFC-2822时间,也就是new Date()出来的时间的长相,之前说了typeof new Date()是对象,把对象变为字符串用toString()
参考资料:
https://segmentfault.com/a/1190000004292140
https://www.xuanfengge.com/js-date-object.html
http://blog.sina.com.cn/s/blog_65415e870102wwnq.html