js 时间的计算

1,547 阅读8分钟

1分钟等于60秒,1小时等于60分钟,一秒钟等于1000毫秒,这是最基础的时间计算

但是计算上周的今天是那一天?某个日期之间相差多少分钟,多少秒?却有些茫然……

使用时间戳来创建日期

在JS中,时间戳是自1970年1月1日(1970年1月1日也称为Unix纪元时间,UTC/GMT的午夜)开始所经过的秒数,不考虑闰秒。 UNIX时间戳的0按照ISO 8601规范为 :1970-01-01T00:00:00Z. 一个小时表示为UNIX时间戳格式为:3600秒(3600x1000毫秒);一天表示为UNIX时间戳为86400秒(86400x1000毫秒),闰秒不计算;

时间戳格式分为两种,13位时间戳计算到毫秒,10位时间戳计算到秒。

获取当前时间的时间戳

var timestamp=new Date().getTime();
复制代码

获取当前日期指定时间的时间戳

// 时间格式必须为 YYYY-MM-DD HH:MM:SS 或者 YYYY-MM-DD
var a=(new Date()).toLocaleDateString()//获取当前日期
a =a.replace(///g,'-');//替换2017/05/03 为    2017-05-03
var b=new Date(a+ '9:00:00').getTime()//获取当日9点的时间戳
var c=new Date(a+ '10:00:00').getTime()//获取当日10点的时间戳
var d=b+600000 //获取十分钟后的时间戳
console.log(c-b) // 3600000 一个小时相差的毫秒数
console.log(new date('Y-m-d H:i:s',d)) // 将d的时间戳转化为时间 输出当日的9点10分
复制代码

创建日期

可以使用 new Date() 来创建日期,传入的参数通常有4种常用的方式:

  1. 使用日期字符串参数
  2. 使用一系列的参数
  3. 时间戳参数
  4. 不带参数

使用日期字符串参数

new Date('1988-03-21')
复制代码

这种方式方便且直观。如果现在写的是21-03-1988,我们可以毫不费力想表达的是1988年3月21日。但是如果用JS 编写21-03-1988,则会得到无效的日期。

image.png

这是有原因的。 在世界的不同地方以不同的方式解释日期字符串。例如11-06-20192019年6月11日还是 2019年11月6日。你不能确定我指的是哪一个,除非你知道我正在使用的日期系统。在JS中,如果要使用日期字符串参数,则需要使用全球都能接受的格式,其中一种格式是ISO 8601扩展格式。

// ISO 8601 Extended format`YYYY-MM-DDTHH:mm:ss:sssZ`
复制代码
  • YYYY:4位数年份
  • MM:两位数月份(即 1月为01,12月为12)
  • DD:两位数的日期(0到31)
  • -:日期分隔符
  • T:表示开始时间
  • HH:24位小时数(0到23)
  • mm:分钟(0到59)
  • ss:秒(0到59)
  • sss:毫秒(0到999)
  • ::时间分隔符
  • Z:如果存在Z,则日期将设置为UTC,如果Z不存在,则为本地时间。

其中小时,分钟,秒和毫秒是可选的,如果你想创建一个2019年6月11日的日期,可以这样写:

new Date('2019-06-11')
复制代码

在这里要特别注意,使用日期字符串参数创建日期存在很大问题,把创建的日期打印出来就可以发现问题。如果你住在**格林威治标准时间(GMT)**晚的的地区,你会得到一个日期是6月10日

image.png

发生这种情况是因为日期字符串参数的方法具有特殊行为:如果创建日期(未指定时间),则会获得UTC格式设置的日期。

在上面的场景中,使用new Date('2019-06-11') 创建日期时,实际上创建的日期是2019年6月11日,UTC时间上午12点。这就是为什么住在格林尼治标准时间之后的地区的人得到的是6月10日而不是6月11日。如果要使用日期字符串参数方法在“本地时间”中创建日期,则需要包括时间。如果包含时间,则需要至少写入HHmm

new Date('2019-06-11T00:00')
复制代码

image.png

使用日期字符串参数的创建的本地时间与UTC的比较可能是一个难以捕捉的错误。所以,建议不要使用日期字符串创建日期方式。

格林威治标准时间GMT
十七世纪,格林威治天文台为了海上霸权的扩张计画而进行天体观测。1675年旧观测所(Old Royal Observatory) 正式成立,到了1884年决定以通过格林威治的子午线作为划分地球东西两半球的经度零度。观测所门口墙上有一个标志24小时的时钟,显示当下的时间,对全球而言,这里所设定的时间是世界时间参考点,全球都以格林威治的时间作为标准来设定时间,这就是我们耳熟能详的「格林威治标准时间(Greenwich Mean Time,简称G.M.T.)的由来,标示在手表上,则代表此表具有两地时间功能,也就是同时可以显示原居地和另一个国度的时间。

世界协调时间UTC
多数的两地时间表都以GMT来表示,但也有些两地时间表上看不到GMT字样,出现的反而是UTC这3个英文字母,究竟何谓UTC?事实上,UTC指的是Coordinated Universal Time- 世界协调时间(又称世界标准时间、世界统一时间),是经过平均太阳时(以格林威治时间GMT为准)、地轴运动修正后的新时标以及以「秒」为单位的国际原子时所综合精算而成的时间,计算过程相当严谨精密,因此若以「世界标准时间」的角度来说,UTC比GMT来得更加精准。其误差值必须保持在0.9秒以内,若大于0.9秒则由位于巴黎的国际地球自转事务中央局发布闰秒,使UTC与地球自转周期一致。所以基本上UTC的本质强调的是比GMT更为精确的世界时间标准,不过对于现行表款来说,GMT与UTC的功能与精确度是没有差别的。

使用一系列的参数创建

最多可以传入七个参数来创建日期/时间。

  1. Year:4位数年份
  2. Month:一年中的某月(0-11)
  3. Day:每月的某天(1-31),如果省略,则默认为1。
  4. Hour:一天中的小时(0-23),如果省略,则默认为0。
  5. Minutes:分钟(0-59),如果省略,则默认为0。
  6. Seconds:秒(0-59),如果省略,则默认为0。
  7. Milliseconds:毫秒(0-999),如果省略,则默认为0。
// 11th June 2019, 5:23:59am, Local Time
   new Date(2019, 5, 11, 5, 23, 59)
复制代码

许多开发人员比较少用这种方式,因为它看起来很复杂,但它实际上非常简单。可以从左到右记忆:年、月、日、小时、分钟、秒和毫秒。Date 中需要注意的地方Month是从0开始的,如1月=== 0,2月=== 1,3月=== 2,依此类推。再来一些事件熟悉一下多个参数的用法

// 21st March 1988, 12am, Local Time.
new Date(1988, 2, 21)
// 25th December 2019, 8am, Local Time.
new Date(2019, 11, 25, 8)
// 6th November 2023, 2:20am, Local Time
new Date(2023, 10, 6, 2, 20)
// 11th June 2019, 5:23:59am, Local Time
new Date(2019, 5, 11, 5, 23, 59)
复制代码

注意,使用参数创建的日期都是用本地时间使用参数的还有一个好处是不会在本地时间和UTC之间混淆,如果需要UTC时间,请以这种方式创建UTC 日期:

// 11th June 2019, 12am, UTC.
new Date(Date.UTC(2019, 5, 11))
复制代码

使用时间戳来创建日期

在JS中,时间戳是自1970年1月1日以来经过的毫秒数(1970年1月1日也称为Unix纪元时间)。根据我的经验,很少使用时间戳来创建日期,一般使用时间戳来比较不同的日期或者格式化日期,后面在讨论。

不带参数的形式创建日期

如果创建没有任何参数的日期,则会将日期设置为当前时间(以本地时间为单位)。

new Date()
复制代码

image.png