全面讲解在JavaScript中获取当前时间戳与Date对象的常见方法、实现原理、两者互相转换技巧及工程实践避坑指南。
JS怎么获取当前时间戳和Date对象
时间:2026-11-02
浏览:588
文章目录
const now = new Date();;如果需要获取当前瞬间的 Unix 毫秒时间戳,最推荐且性能最高的方式是调用静态方法 const ts = Date.now();。
假设你正在编写一个前端数据提交模块,或者在 Node.js 服务端处理一次支付请求。为了记录该操作的准确发生时间,你通常面临两种选择:一种是将时间转换为带有年月日、时分秒以及本地时区的可读结构(如 2026-11-01 19:25:00),这依赖于 Date 对象;另一种是直接获取一段纯数字标记(如 1730460300000),以便于网络传输、数据库索引和防重放校验,这正是时间戳的职责。
一、获取当前 Date 对象并提取时间分量
通过构造函数 new Date() 可以无参数创建一个全新的日期对象实例。在实例创建的瞬间,JavaScript 引擎会向底层操作系统读取当前系统时钟,并以此封装出一个带有本地时区偏移信息的对象。
const now = new Date();
console.log(now);
// 示例输出(标准 UTC ISO 字符串):2026-11-01T11:25:00.000Z
// 示例输出(本地可读字符串):Sun Nov 01 2026 19:25:00 GMT+0800 (中国标准时间)
获得 Date 实例后,通常需要从对象中提取具体的年、月、日、时、分、秒等分量,并按需求拼接为规范字符串。这一操作可通过原型链上的常用 Getter 方法完成:
const now = new Date();
const year = now.getFullYear(); // 获取四位数年份,例如 2026
const month = now.getMonth() + 1; // 关键注意:返回值范围为 0 ~ 11,实际月份必须 +1
const date = now.getDate(); // 获取当月第几天 (1 ~ 31)
const day = now.getDay(); // 获取星期几 (0 表示周日,1 ~ 6 表示周一至周六)
const hours = now.getHours(); // 获取小时 (0 ~ 23)
const minutes = now.getMinutes(); // 获取分钟 (0 ~ 59)
const seconds = now.getSeconds(); // 获取秒数 (0 ~ 59)
const ms = now.getMilliseconds(); // 获取毫秒数 (0 ~ 999)
// 格式化为双位数标准字符串(前置补零)
const pad = (n) => String(n).padStart(2, '0');
const formatted = `${year}-${pad(month)}-${pad(date)} ${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
console.log(formatted);
// 示例输出:2026-11-01 19:25:00
getYear() 方法,该方法返回的是“当前年份减去 1900”的值;务必始终使用 getFullYear()。同时,getMonth() 从 0 开始索引是新手开发者最容易忽略的细节。
二、理解 Date 对象与时间戳的底层映射关系
在深入各种时间戳获取写法之前,有必要先理清两者的内核联系。在 ECMAScript 规范定义中,任何一个 Date 对象内部实际上只保存了一个核心数值——即距离 1970 年 1 月 1 日 00:00:00 UTC(Unix 纪元) 的毫秒数计数。
换句话说,时间戳是底层没有任何时区污染的绝对时间刻度,而 Date 对象是这个刻度加上宿主环境本地时区(如 GMT+0800)之后的高级封装形式。
正因为两者内部共享相同的数值实质,因此它们之间可以随时无损双向转换:
- Date 对象转换为时间戳:调用
now.getTime()或now.valueOf(),即可拆包取出内部的 13 位毫秒数值。 - 时间戳封装为 Date 对象:调用
new Date(timestamp),即可将纯数字毫秒还原为带有完整操作方法的日期对象。
三、获取当前时间戳的四种常见写法与深度对比
在日常开发与历史代码阅读中,你可能会见到四种不同的时间戳获取语法。它们在底层运作与性能开销上存在明显区别:
1. Date.now()(首选标准方案)
这是 ECMAScript 5 正式引入的静态方法。它直接向运行时系统查询当前时刻并返回 13 位毫秒数字,完全不会在内存中创建任何临时 Date 实例。不仅语义明确、阅读体验极佳,而且在需要高频采集时间戳(如高频日志记录、轮询请求标记)的场景下性能最佳,没有任何垃圾回收(GC)负担。
const timestamp = Date.now();
console.log(timestamp);
// 示例输出:1730460300000
2. +new Date()(常见语法糖简写)
这种写法利用了 JavaScript 的一元加号运算符(+)。一元加号会强制将后面的操作数转换为数字类型,内部会自动调用 Date.prototype.valueOf(),进而返回该实例的时间戳。这种写法虽然字节较少,但每次执行都会在堆内存中创建并销毁一个 Date 对象,属于较为隐晦的技巧性代码。
const timestamp = +new Date();
console.log(timestamp);
// 示例输出:1730460300000
3. new Date().getTime() 或 new Date().valueOf()(传统向下兼容写法)
这是在 ES5 以前(如早期的 IE8 等极老旧环境)最标准做法。它先通过 new Date() 实例化一个对象,再显式调用其原型链上的 getTime() 方法。它的意图虽然清晰,但与 Date.now() 相比多出了一次对象创建与方法查找的开销。在现代项目中,直接获取时间戳时不建议继续采用此写法。
const timestamp = new Date().getTime();
console.log(timestamp);
// 示例输出:1730460300000
4. performance.now()(专用于性能分析与耗时测量)
如果获取时间的目的是为了测量某段代码、动画帧或网络请求的执行耗时,不要使用 Date.now(),而应使用 performance.now()。
原因在于:Date.now() 依赖于宿主操作系统的时钟,如果操作系统在运行期间进行了网络对时(NTP 同步)或用户手动修改了本地时间,Date.now() 的差值可能产生剧烈跳变甚至出现负数。而 performance.now() 基于单调递增时钟(Monotonic Clock),返回自当前上下文(如页面载入)以来的高精度微秒级浮点数,不会被系统时钟调整干扰。
const start = performance.now();
// 执行一些计算逻辑...
for (let i = 0; i < 1000000; i++) {}
const end = performance.now();
console.log(`执行耗时:${(end - start).toFixed(3)} 毫秒`);
// 示例输出:执行耗时:1.428 毫秒
四、秒级时间戳转换与工程实践注意事项
1. 13 位毫秒戳与 10 位秒级时间戳的转换
在实际项目对接中,许多后端语言或接口规范(如 Linux 系统调用、PHP、OAuth 鉴权协议)默认约定使用 10 位的“秒级时间戳”。而 JavaScript 原生返回的始终是 13 位“毫秒级时间戳”。
两者的转换规则如下:
// 1. 获取当前 10 位秒级时间戳(直接除以 1000 并向下取整)
const unixSec = Math.floor(Date.now() / 1000);
console.log(unixSec);
// 示例输出:1730460300
// 2. 从后端接收到 10 位秒级时间戳并转换为 JS Date 对象(必须先乘以 1000)
const backendSec = 1730460300;
const dateObj = new Date(backendSec * 1000);
console.log(dateObj.toLocaleString());
// 示例输出:2026/11/1 19:25:00
new Date(1730460300),由于缺少 3 个 0,JavaScript 会将其解释为 1970 年 1 月 21 日附近的时间。排查时间异常 bug 时,检查时间戳位数往往是最快定位问题的手段。
2. 客户端时间不可信原则
浏览器端运行的 Date.now() 和 new Date() 完全依赖用户当前电脑或手机的本地系统时间。如果用户的系统时间存在偏差,或者恶意篡改了本地时钟,获取到的时间戳就会失真。
因此,对于关键业务逻辑(如订单倒计时、活动开始校验、权限令牌过期判断),切忌完全信任客户端获取的时间戳,而应在初始化时由服务端返回一个权威基准时间,或者在关键节点由服务端负责最终判定。
五、总结与技术选型决策
理解了 Date 对象与时间戳的区别和特性后,面对具体业务场景,可以参照如下逻辑快速做出选择:
- 需要构建界面文字、提取特定年月日、或进行本地时区转换:直接使用
new Date()。 - 需要向服务端发送通用时间戳、记录操作日志、生成时间序列 ID:首选静态方法
Date.now()(若服务端要求秒级则追加Math.floor(Date.now() / 1000))。 - 需要测量前端函数运行耗时、统计动画或网络请求延迟:使用单调递增的
performance.now()。
实用工具推荐
绿化、压缩、噪点和虚拟水印,自由调节做旧程度。
选择画质和输出格式,预览压缩前后的大小。