Day.js和Moment.js中获取时间戳的API用法
详细讲解在Day.js和Moment.js中获取13位毫秒级与10位秒级时间戳的核心API用法,对比valueOf、unix、隐式转换等方法的使用场景、反向解析机制与避坑要点。
.valueOf(),获取 10位秒级时间戳 使用 .unix()。本文详细梳理两者的核心 API 调用方式、类型特征、反向解析方法及高频陷阱,帮助开发者规范、准确地处理时间戳数据。
一、时间戳精度区分:13位毫秒与10位秒
在讨论 API 之前,必须先明确 JavaScript 生态中两类常见的时间戳概念:
- 13 位毫秒级时间戳(Milliseconds):指从 Unix 纪元(1970年1月1日 00:00:00 UTC)起至当前时刻经过的毫秒数,例如
1700000000000。原生 JavaScript 中的Date.now()和new Date().getTime()默认返回的正是此精度。 - 10 位秒级时间戳(Seconds / Unix Timestamp):指自 Unix 纪元起经过的整秒数,例如
1700000000。在后端接口设计、Linux 系统接口以及各类开放协议(如 OAuth)中更为普遍。
Day.js 在设计上最大程度保持了对 Moment.js API 的兼容,因此在这两类时间戳的获取上,两个库的函数名称与行为几乎完全一致。
二、获取毫秒级时间戳(13位)的具体 API 与用法
获取 13 位毫秒级时间戳通常有以下几种方式,推荐首选语义清晰的 .valueOf() 方法。
1. 使用 .valueOf() 方法
.valueOf() 会返回以毫秒为单位的数字(number 类型),表示 Unix 纪元至今的微秒/毫秒偏移。
// Day.js 示例
const dayjs = require('dayjs');
const msDay = dayjs().valueOf();
console.log(msDay); // 示例输出: 1714521600000
console.log(typeof msDay); // 示例输出: "number"
// Moment.js 示例
const moment = require('moment');
const msMoment = moment().valueOf();
console.log(msMoment); // 示例输出: 1714521600000
console.log(typeof msMoment); // 示例输出: "number"
2. 使用一元加号操作符(+ 隐式类型转换)
在 JavaScript 中,当对一个对象使用一元加号 + 时,JS 引擎会内部调用对象的 valueOf() 方法,将其强制转换为原始数值类型。因此 +dayjs() 和 +moment() 是简洁的等效写法:
const timestamp1 = +dayjs(); // 1714521600000
const timestamp2 = +moment(); // 1714521600000
3. 转为原生 Date 对象后获取(.toDate().getTime())
如果需要配合只接受原生 Date 的遗留库,可通过 .toDate() 取出原生 Date 实例,再调用其原生的 .getTime():
const jsDateMs = dayjs().toDate().getTime(); // 1714521600000
三、获取秒级时间戳(10位)的具体 API 与用法
在后端服务交互、数据签名、Token 过期时间计算等场景中,经常需要 10 位的 Unix 秒级时间戳。Day.js 和 Moment.js 提供了极其简洁的方法:
1. 使用 .unix() 方法
调用 .unix() 可以直接得到自 1970-01-01 00:00:00 UTC 算起的秒数。它返回的是一个经过向下取整的整数(number 类型)。
// Day.js
const dayjs = require('dayjs');
const secDay = dayjs().unix();
console.log(secDay); // 示例输出: 1714521600
console.log(typeof secDay); // 示例输出: "number"
// Moment.js
const moment = require('moment');
const secMoment = moment().unix();
console.log(secMoment); // 示例输出: 1714521600
console.log(typeof secMoment); // 示例输出: "number"
2. 手动取整转换(底层计算逻辑)
两个库内部对于 .unix() 的实现逻辑实际上都等价于:
const manualSec = Math.floor(instance.valueOf() / 1000);
了解这一原理可以帮助我们理解:在秒级转换时,当前秒内的毫秒部分会被舍弃(向下取整截断),因此从秒级时间戳反转回毫秒时,末尾三位总是 000。
四、Day.js 与 Moment.js 的差异与底层机制分析
虽然两者的 API 名称一致,但在底层对象机制上存在重大差异:不可变性(Immutability)。
- Moment.js 的可变对象陷阱:在 Moment.js 中,调用
.add()、.subtract()等方法会直接修改原有对象本身。如果在一个实例上连续链式运算并获取时间戳,原对象已经被改变。 - Day.js 的不可变性:Day.js 借鉴了现代函数式编程理念,所有的日期修改操作均返回一个新的 Dayjs 实例,原有对象永远保持只读。
// Moment.js 可变性测试
const m1 = moment('2024-05-01');
const m2 = m1.add(1, 'day');
console.log(m1.valueOf() === m2.valueOf()); // true!m1 被连带修改了
// Day.js 不可变性测试
const d1 = dayjs('2024-05-01');
const d2 = d1.add(1, 'day');
console.log(d1.valueOf() === d2.valueOf()); // false!d1 保持不变
五、时间戳反向解析(Timestamp to Date/Object)
在实际开发中,获取时间戳的下一环通常是解析接收到的时间戳。针对 13 位毫秒和 10 位秒,解析入口必须严格对应:
1. 解析 13 位毫秒级时间戳
对于毫秒级时间戳,直接传入主函数构造器即可:
const msValue = 1714521600000;
// Day.js
const dateFromDay = dayjs(msValue);
console.log(dateFromDay.format('YYYY-MM-DD HH:mm:ss'));
// Moment.js
const dateFromMoment = moment(msValue);
console.log(dateFromMoment.format('YYYY-MM-DD HH:mm:ss'));
2. 解析 10 位秒级时间戳
若将 10 位秒级时间戳误当作毫秒直接传入 dayjs(1714521600),会被解析为 1970 年 1 月的最初几十天(因为被当成了 171 万毫秒)。解析 10 位时间戳必须使用 .unix() 静态方法:
const secValue = 1714521600;
// 正确做法:使用静态工厂方法 .unix()
const d = dayjs.unix(secValue); // Day.js 正确解析
const m = moment.unix(secValue); // Moment.js 正确解析
// 或者手动乘以 1000 转为毫秒:
const dManual = dayjs(secValue * 1000);
六、实际开发中容易混淆的常见陷阱与注意事项
1. 时区与时间戳的独立性
无论当前电脑处于东八区(UTC+8)还是格林威治(UTC+0),同一时刻调用 dayjs().valueOf() 得到的数值必然相同。许多初学者常误以为切换到 UTC 模式后时间戳会相差 8 个小时,实际调用 dayjs().utc().valueOf() 与 dayjs().valueOf() 的结果完全相等。时区只影响时间戳格式化为文本(如 YYYY-MM-DD HH:mm:ss)时的展示。
2. 使用 .format('X') 与 .format('x') 获取的是字符串而不是数值
除了 .valueOf() 和 .unix() 之外,格式化方法也支持时间戳占位符:
instance.format('x'):返回 13 位毫秒级时间戳字符串。instance.format('X'):返回 10 位秒级时间戳字符串。
.valueOf() 和 .unix() 的返回值是纯数字(number),而 .format() 的返回值永远是字符串(string)。在需要进行数值比大小或传输给只接受数值的后端接口时,切忌直接混用。
3. 避免将 10 位秒级时间戳直接传给 dayjs()
如前文所述,在接收服务端返回的时间戳时,务必先确认长度是 10 位还是 13 位:
// 健壮的动态解析函数示例
function parseTimestamp(ts) {
const num = Number(ts);
// 10位秒级(小于 1000 亿)按 unix 解析,否则按毫秒解析
return num < 100000000000 ? dayjs.unix(num) : dayjs(num);
}
七、API 选型与速查总结
为了在实际编码时快速查阅,以下总结了 Day.js 与 Moment.js 获取时间戳及相关操作的速查表:
| 目标任务 | Day.js API | Moment.js API | 返回值类型 | 典型输出示例 |
|---|---|---|---|---|
| 获取 13 位毫秒时间戳 | dayjs().valueOf() 或 +dayjs() |
moment().valueOf() 或 +moment() |
number | 1714521600000 |
| 获取 10 位秒级时间戳 | dayjs().unix() |
moment().unix() |
number | 1714521600 |
| 获取毫秒字符串 | dayjs().format('x') |
moment().format('x') |
string | "1714521600000" |
| 获取秒级字符串 | dayjs().format('X') |
moment().format('X') |
string | "1714521600" |
| 从 13 位毫秒反向解析 | dayjs(ms) |
moment(ms) |
Dayjs / Moment 实例 | 包装对象 |
| 从 10 位秒级反向解析 | dayjs.unix(sec) |
moment.unix(sec) |
Dayjs / Moment 实例 | 包装对象 |
JS大数值转字符串出现科学计数法怎么办
2026-11-05 17:09:21
JS split切割后出现空字符串怎么过滤
2026-11-05 16:00:30
在 React 或 Vue 项目中封装使用 JS 节流防抖
2026-11-05 15:27:29
JavaScript中怎么将带小数的字符串转为整数?
2026-11-05 14:32:38
怎么用JavaScript策略模式重构电商促销计算逻辑?
2026-11-05 14:01:09








