平时对 Date 很多内容都一知半解,每次一用到 Date 就需要查资料,着实恼火。
故此文记录关于 JS 日期操作那些我不知道的事。

基础问题

Date.prototype.getTime() 返回的数字是什么?

官方对getTime 函数对定义是

The getTime() method returns the number of milliseconds* since the Unix Epoch

getTime() 函数返回从 Unix Epoch 开始到当前 Date 所指时间经过的毫秒数。

Unix Epoch 是什么呢?

1970年1月1日(UTC/GMT的午夜)

所以 getTime() 返回的数字是从 1970年1月1日0时0分0秒开始到当前 Date 对象所指时间所经过的毫秒数

例如:

getTime() 和你所在的时区也有关系,我国的标准时间是北京时间,在东八区,所以比英国格林威治时间(GMT)的 0 时区晚 8 个小时。所以我定义的 1970年1月1日使用 getTime 函数得到 -2880000,即 8 小时。

GMT 和 UTC 是什么,有什么区别?

GMT(格林尼治标准时间) 和 UTC(协调世界时) 是计算世界时间的两种标准。

GMT 根据地球的自转和公转来计算时间,也就是太阳每天经过位于英国伦敦郊区的皇家格林威治天文台的时间就是中午12点。UTC是根据原子钟来计算时间,目前世界上最精确的原子钟50亿年才会误差1秒。因为地球的自传正在缓速变慢,会导致 GMT 计算有误差,所以 UTC 比 GMT 更加精确。UTC 时间被认为能与GMT 时间互换,但 GMT 时间已不再被科学界所确定。

PS:两个都是 0 时区的时间,例如:UTC +8 = 北京时间。

Date.getMonth() 为什么要从 0 开始

谁能想到这是 Java 埋的坑,因为 Javascript 的 Date 实现方案是 JDK1.0 的方案,所以坑也一样。
Javascript 之父用一句 Make It Look Like Java 调侃了这个坑也告诉了我们答案。

问题来了,Java 获取月份为什么要从 0 开始呢?

  • 说法 1: 可能是因为旧的 C 语言日期 API 是这样的,那么旧的 C 语言日期 API 为什么是这样呢?…不套娃了。
  • 说法 2:计算机里面所有东西都从 0 开始
  • 说法 3:从 0 开始做月份计算更加容易

例如 12 月的下一个月份是 1 月,不过为了计算出 1 月你会做以下计算:

12 + 1 = 13 // 13 月是哪个月?

我们可以用 12 取余快速修复上面的问题

(12 + 1) % 12 = 1

但是当遇到 11 月的时候…

(11 + 1) % 12 = 0 // 0 月是哪个月?

您可以在添加月份之前先减去1,然后再进行取余运算,最后再加1,就可以修复上面的问题…也可以解决这个“基本问题”。

((11 - 1 + 1) % 12) + 1 = 12 // 许多神奇的数字!

现在我们来看看如果月份的数字是 0 - 11,会有什么问题?

(0 + 1) % 12 = 1 // February
(1 + 1) % 12 = 2 // March
(2 + 1) % 12 = 3 // April
(3 + 1) % 12 = 4 // May
(4 + 1) % 12 = 5 // June
(5 + 1) % 12 = 6 // July
(6 + 1) % 12 = 7 // August
(7 + 1) % 12 = 8 // September
(8 + 1) % 12 = 9 // October
(9 + 1) % 12 = 10 // November
(10 + 1) % 12 = 11 // December
(11 + 1) % 12 = 0 // January

所有月份的表现一致,无需较复杂的解决方案。

时间戳是什么?

常指 unix 时间戳,上文提到过:从1970年1月1日(UTC/GMT的午夜)开始所经过的秒数。
获取时间戳的代码:

Math.round(new Date().getTime()/1000)

常用方法

定义时间的方法

传入时间格式的字符串

new Date('September 11, 1995 03:24:00')
new Date('1995-09-11T03:24:00')
new Date('Mon Sep 11 1995')

不同的浏览器实现有差异,强烈不建议使用字符串初始化/解析日期。建议使用传入数字初始化日期对象。相同的浏览器针对不同的定义方式也有些许差异。

例子1:

new Date(Date.parse("Jul 8, 2005"));//Fri Jul 08 2005 00:00:00 GMT+0800 (China Standard Time)
new Date(Date.parse("2005-07-08"));//Fri Jul 08 2005 08:00:00 GMT+0800 (China Standard Time)

例子2:在 2020年以前的,Firefox 和 Chrome 针对以下代码实现有差异。

Date.parse('1970-01-01T00:00:00Z');       // Chrome: 0         FF: 0
Date.parse('1970-01-01T00:00:00-0500');   // Chrome:18000000  FF: 18000000
Date.parse('1970-01-01T00:00:00');        // Chrome: 0 FF: -28800000

传入多个时间单位的数字

new Date(1995, 8, 11)//注意,月份需要减 1,例如定义 9 月,第二个月份参数需要传 8
new Date(1995, 8, 11, 3, 24, 0)

传入 Unix 时间戳

new Date(810761040000) //Mon Sep 11 1995 03:24:00 GMT+0800 (China Standard Time)

时间的加减法

减法

首先,需要将你的日期转化为 Date 对象,然后直接使用加减符号计算差。得到的结果是和或差的毫秒数,再将毫秒转化成你需要的格式。例如 2020-01-01 和 2020-01-02 差多久?

new Date(2020,0,2)-new Date(2020,0,1)//86400000[ms]

如果结果是要计算差多少天,即是 86400000 除以 1000得到秒数,再除以 60 得到分钟数,以此类推。

86400000/1000/60/60/24 //1

加法

两个 Date 相减能得到毫秒,那理所当然地某个 Date 加上毫秒数就可以等于另一个日期了。例如 2020-01-01 加上 86400000 毫秒,就等于 2020-01-02
No!No!No!

new Date(2020,0,1)+86400000
//Wed Jan 01 2020 00:00:00 GMT+0800 (China Standard Time)86400000

我还是太年轻了,跨类型的两个对象,强行加在一起,不甜。

1.转换成数字相加

将 new Date(2020,0,1) 转换成毫秒,来到整形的世界,快乐地计算。

(new Date(2020,0,1).getTime()+86400000)
//Thu Jan 02 2020 00:00:00 GMT+0800 (China Standard Time)

2.使用 JS 内置方法

加减年、月、日、时、分、秒。例如:

var date=new Date(2020,0,1);
date.setDate(date.getDate()+1)
//date:Thu Jan 02 2020 00:00:00 GMT+0800 (China Standard Time)

不同的时间单位的加法使用的方法不同,可以根据下表选择对应的方法。

单位 获取时间 设置时间 例子
getSeconds setSeconds date.setSeconds(date.getSeconds()+1)
getMinutes setMinutes date.setMinutes(date.getMinutes()+1)
getHours setHours date.setHours(date.getHours()+1)
getDate setDate date.setDate(date.getDate()+1)
setFullYear getFullYear date.setFullYear(date.getFullYear() + x)
getMonth setMonth date.setMonth(date.getMonth()+1)
setFullYear getFullYear date.setFullYear(date.getFullYear() + x)

比较时间的大小

获取毫秒数,进行数字大小的比较。

new Date(2020,0,1).getTime()>=new Date(2020,0,1).getTime() //true

获取不同格式的当前时间

toString()

new Date().toString();
//Fri Sep 18 2020 00:18:59 GMT+0800 (China Standard Time)"

toLocaleString()

new Date().toLocaleString();
// 9/18/2020, 12:18:16 AM

toUTCString()/toGMTString()

new Date().toUTCString();
new Date().toGMTString();
//Thu, 17 Sep 2020 16:10:04 GMT

GMT 已经不被推荐使用了,原因在上文提到过:UTC 比 GMT 精确。

toISOString()

new Date().toISOString();
//2020-09-17T16:20:06.419Z

返回 ISO 格式 (ISO 8601)的日期。

ISO 格式日期的规则是生成格式为 YYYY-MM-DDTHH:mm:ss.sssZ 或者 ±YYYYYY-MM-DDTHH:mm:ss.sssZ24 位到 27 位字符串。

YYYY-MM-DDTHH:mm:ss.sssZ 里面的 T 是分隔日期和时间的符号。

YYYY-MM-DDTHH:mm:ss.sssZ 里面的 Z 是时区的占位符,可以不写时区用 Z 代替是 0 时区,也可以使用 2020-09-17T00:20:06+08:00 代表东八区。

资料

  • MDN-Date
  • 知乎-UTC和GMT什么关系?
  • 知乎-JavaScript中的Date对象取值month为什么是从0开始的?
  • stackoverflow-why-is-january-month-0-in-java-calendar

JavaScript 日期操作我不知道的事情相关推荐

  1. 自2018年以来我不知道的事情-Dan Abramov

    原文地址哈:https://overreacted.io/things-i-dont-know-as-of-2018/ 人们常常假设我知道的知识远比实际知识道的多.我不抱怨这个错误的想法.(拥有些许成 ...

  2. 读书 | 5件富人都在做穷人却不知道的事情

    作者 | 杨小爱 习惯,就是我们长期以来养成的行为方式,这是美国作家托马斯科里在<富有的习惯>一书中对习惯的定义. 而我对习惯的理解就是,习惯就好像我们每天起床后会自然而然的去洗脸刷牙一样 ...

  3. 要想步入程序开发行列,就不得不知道的事情汇总

    前言 当迈入程序开发行列之后,就意味着从此与程序开发"相依为命".不管你已经迈入程序开发行列,还是即将迈入,一些做程序开发必知内容是需要提前知道的.尤其是打算做程序开发的大学生朋友 ...

  4. 你的QQ号又被盗了?关于网络安全你所不知道的事情

    不知道大家是否有这样一个经历: 就是大家的qq好像被别人登录了一样,群发给朋友,向朋友借钱的消息,有些身边的朋友还被骗取了大量的金额,别人又是如何知道自己的密码的呢? 现在都0202年了,想说的是QQ ...

  5. CE6 驱动: 你不得不知道的事情

    许多人担心CE6驱动的向后兼容性.在CE6上,应用程序和OAL可以比较良好的兼容,但驱动就比较难.驱动在移植到CE6上必须做一定的修改,原封不动的放到CE6上运行是不太可能的. 驱动需要修改的主要原因 ...

  6. 关于多线程编程您不知道的 5 件事 有关高性能线程处理的微妙之处

    虽然很少有 Java™ 开发人员能够忽视多线程编程和支持它的 Java 平台库,更少有人有时间深入研究线程.相反地,我们临时学习线程,在需要时向我们的工具箱添加新的技巧和技术.以这种方式构建和运行适当 ...

  7. 祝贺!屠呦呦再获国际大奖!一文读懂:神药青蒿素那些我们不知道的事

    又有好消息传来!总部位于法国巴黎的联合国教科文组织10月22日公布2019年度联合国教科文组织-赤道几内亚国际生命科学研究奖获奖名单,共3人获奖,其中包括来自中国的屠呦呦. 此前,屠呦呦先后拿下多项大 ...

  8. 关于PHP你可能不知道的10件事

    小编之前也曾报导过PHP开发人员容易忽略的几点精华,除了一些精华技术方法外,很多细微之处也是程序员们容易忽略的,下面我们为您总结了10个关于PHP你可能不知道的事情. 关于PHP更多内容,欢迎访问:P ...

  9. LHS 和 RHS---你所不知道的JavaScript

    目录 1.LHS(Left Hand Side)和 RHS(Right Hand Side) 2.实例详解 3.总结 变量的赋值操作会执行两个动作, 首先编译器会在当前作用域中声明一个变量(如果之前没 ...

最新文章

  1. 使用OpenCV,Numpy计算直方图,Matplot绘制直方图及分析
  2. 【目录】C#操作Excel组件Spire.XLS系列文章目录
  3. 成功解决ValueError: DataFrame.dtypes for data must be int, float or bool.Did not expect the data types
  4. HTML实现包含公共部分:通过ECMA6的模块化,纯前端实现类似jsp:include的功能
  5. Linux 设备树 : 节点与属性的删除
  6. 不要忽视任何小问题!!!一个XML的XPath的问题.....
  7. 关于DruidStatView监控信息
  8. ACM算法--二分法--模板
  9. 服务端解决跨域问题的方案(二)
  10. c语言组成整数的最大数字,c语言 编写程序将一个正整数中的所有偶数数字取出来并用这些数字构成一个最大数。...
  11. hadoop安装及简单的使用
  12. SWF怎么转FLV格式?
  13. 论文阅读笔记—Exploring Visual Relationship for Image Captioning
  14. angularjs防抖
  15. 基地树洞 | 自动化小系列之番外篇
  16. android-自定义锁屏界面
  17. php文件断点上传文件,php大文件上传支持断点上传
  18. 安利安卓模拟器-夜神模拟器
  19. 【C++程序设计Ⅱ 兼谈对象模型 ——侯捷大师】心得摘要
  20. [精简]托福核心词汇100

热门文章

  1. html+css实现必要等商城页面
  2. imx533 配置 制作SD卡启动文件系统
  3. 蓝桥杯评分标准_第十届蓝桥杯软件个人赛校内选拔赛评分标准和选拔标准.doc...
  4. mac、parallel是什么
  5. 数据结构算法【考研】
  6. ABAQUS INP文件详解
  7. 证件照还用去照相馆别费钱了自己就能搞定
  8. 《都挺好》苏明哲为什么会失业,美国程序员不好找工作吗?
  9. java毕业设计学生考勤系统Mybatis+系统+数据库+调试部署
  10. webpack面试题合集