时间戳完全指南
一、时间戳是什么?
时间戳(Timestamp),简单来说就是从1970年1月1日0时0分0秒(UTC) 到当前时间点所经过的秒数(或毫秒数)。这个起点在计算机领域被称为 “时间纪元”(Epoch Time) 。
举个例子,时间戳 1717248000000 这个数字,对应的就是2024年6月1日00:00:00 UTC——不过在不同时区的本地时间会不同,比如北京时间是2024年6月1日08:00:00。
一个关键概念:时间戳是“绝对时间”,不随时区变化。同一个时间戳
1717248000000,在纽约是2024年5月31日16:00:00,在北京是2024年6月1日08:00:00,但时间戳本身完全一样。
二、为什么是1970年1月1日?——时间戳的来历
2.1 Unix的诞生
1969年8月,贝尔实验室的程序员肯·汤普逊利用妻儿离开一个月的机会,在PDP-7机器上用B语言开发出了Unix操作系统的第一个版本。随后,汤普逊和同事丹尼斯·里奇改进了B语言,开发出了C语言,并用C语言重写了Unix,新版于1971年发布。
Unix诞生后,需要在操作系统上表示时间,于是Unix时间戳被定义出来——通过当前时间与一个“纪元时间”的差值(秒数)来表示时间。
2.2 从1971到1970的调整
最初,Unix的开发者把纪元时间定为了1971年1月1日——也就是Unix正式发布的时间。而且最初的时间戳也不是每1秒变动一次,而是每1/60秒变动一次。
但问题很快就来了:当时的计算机系统是32位的,32位有符号整数最大值是 2^31 - 1 = 2147483647。如果用“每1/60秒变动一次”的方式来计算,Unix时间戳最多只能表示约828.5天——一个只能表示两年多时间的系统,显然不实用。
于是开发者做了一次重要调整:
-
把时间戳的变动频率从“每1/60秒”改为每1秒变动一次,可表示的时间一下子放大了60倍;
-
把纪元时间从1971-01-01向前调整到1970-01-01,方便记忆和使用。
从此,1970年1月1日00:00:00 UTC就成为了计算机世界的时间起点,并被后续几乎所有的编程语言和操作系统继承。
2.3 32位系统的“2038年问题”
32位系统能表示的最大秒数是 2147483647 秒,换算一下大约是68年。从1970年开始算,这个最大值将在2038年1月19日03:14:07到达。
过了这个时间点,32位系统的时钟会溢出回绕,变成1901年12月13日——这就是著名的 “2038年问题” 。好在随着64位系统的普及,这个问题已被大大缓解——64位时间戳可以支持到约2922亿年之后。
三、时间戳能做什么?——应用场景
时间戳在软件开发中应用极其广泛:
-
日志记录:记录事件发生的精确时间,方便排查和分析问题
-
数据库记录:记录数据的创建和修改时间
-
缓存策略:基于时间戳判断缓存是否过期
-
数据同步:在分布式系统中用时间戳确定数据的最新版本
-
会话管理:设置会话的超时时间
-
时间差计算:两个时间戳相减即可得到精确的时间差
-
生成唯一ID:时间戳常作为唯一标识符的一部分
四、JavaScript中的时间戳操作
4.1 重要提醒:JS时间戳单位是毫秒!
JavaScript中的时间戳是指从1970年1月1日00:00:00 UTC到当前时间的毫秒数。而很多后端语言(如PHP)的时间戳单位是秒。
跨语言传递时间戳时,一定要注意单位换算:1秒 = 1000毫秒。
4.2 获取当前时间戳
javascript
// 方法1:Date.now() —— 最简洁,推荐
const timestamp = Date.now();
console.log(timestamp); // 示例:1717251689234
// 方法2:new Date().getTime() —— 兼容性好
const timestamp2 = new Date().getTime();
// 方法3:new Date().valueOf()
const timestamp3 = new Date().valueOf();
// 方法4:+new Date() —— 利用类型转换的“黑魔法”
const timestamp4 = +new Date();
Date.now() 是ES5.1新增的方法,语法最简单、性能最优,是日常开发的首选。如果需要兼容IE8及以下的老旧浏览器,则使用 new Date().getTime()。
4.3 时间戳转Date对象
javascript
// 假设有一个毫秒级时间戳
const timestamp = 1717251689234;
// 直接传入Date构造函数
const date = new Date(timestamp);
console.log(date.toString());
// 输出:Sat Jun 01 2024 22:21:29 GMT+0800 (中国标准时间)
如果拿到的是秒级时间戳(比如从PHP接口返回的),需要先乘以1000再传入:
javascript
const secondsTimestamp = 1717251689; // 秒级时间戳
const date = new Date(secondsTimestamp * 1000);
4.4 时间戳转格式化日期字符串
方法一:使用Date对象的内置方法
javascript
function formatTimestamp(timestamp) {
const date = new Date(timestamp);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
console.log(formatTimestamp(1717251689234));
// 输出:2024-06-01 22:21:29
方法二:使用toLocaleString
javascript
const date = new Date(1717251689234);
// 转为本地时间字符串
console.log(date.toLocaleString());
// 输出:2024/6/1 22:21:29
// 可指定更多选项
console.log(date.toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
}));
方法三:使用toISOString(输出UTC时间)
javascript
const date = new Date(1717251689234);
console.log(date.toISOString());
// 输出:2024-06-01T14:21:29.234Z
// 注意:这里输出的是UTC时间,末尾的Z表示零时区
toISOString() 返回的是UTC格式的字符串,格式固定为 YYYY-MM-DDTHH:mm:ss.sssZ。
4.5 日期字符串转时间戳
javascript
// 方法1:直接传字符串
const timestamp = new Date('2024-06-01 22:21:29').getTime();
// 方法2:传标准格式
const timestamp2 = new Date('2024-06-01T22:21:29+08:00').getTime();
// 方法3:使用Date.parse()
const timestamp3 = Date.parse('2024-06-01 22:21:29');
注意:不同浏览器对日期字符串的解析可能有差异,建议使用ISO标准格式 YYYY-MM-DDTHH:mm:ss。
五、时区与时间戳
5.1 核心原则
时间戳本身不包含时区信息,它是一个绝对的、全球统一的时间度量。
无论在世界的哪个角落,Date.now() 返回的值都是一样的。区别只在于将时间戳转换为人可读的日期时间时,会使用本地时区进行显示。
5.2 查看当前时区偏移
javascript
// 获取当前时区与UTC的偏移量(分钟)
const offset = new Date().getTimezoneOffset();
console.log(offset);
// 中国标准时间(UTC+8)输出:-480
// 注意:正值表示西时区,负值表示东时区
5.3 在不同时区显示时间
方法一:使用toLocaleString指定时区
javascript
const date = new Date(1717251689234);
// 显示为北京时间(UTC+8)
console.log(date.toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' }));
// 输出:2024/6/1 22:21:29
// 显示为纽约时间(UTC-4/5)
console.log(date.toLocaleString('en-US', { timeZone: 'America/New_York' }));
// 输出:6/1/2024, 10:21:29 AM
// 显示为伦敦时间(UTC+0/1)
console.log(date.toLocaleString('en-GB', { timeZone: 'Europe/London' }));
// 输出:01/06/2024, 15:21:29
方法二:使用Intl.DateTimeFormat
javascript
const date = new Date(1717251689234);
const formatter = new Intl.DateTimeFormat('zh-CN', {
timeZone: 'America/New_York',
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
});
console.log(formatter.format(date));
// 输出:2024/06/01 10:21:29
Intl.DateTimeFormat 是JavaScript内置的国际化API,支持IANA时区标识符(如 Asia/Shanghai、America/New_York),能正确处理夏令时。
方法三:手动进行时区偏移计算
javascript
/**
* 将时间戳转换为指定时区的时间字符串
* @param {number} timestamp - 毫秒级时间戳
* @param {number} zoneOffset - 目标时区偏移小时数(如东八区为8)
*/
function convertToTimeZone(timestamp, zoneOffset) {
const date = new Date(timestamp);
// 获取本地时区与UTC的偏移(分钟)
const localOffset = date.getTimezoneOffset();
// 计算目标时区的时间戳
const targetTime = timestamp + (localOffset + zoneOffset * 60) * 60000;
return new Date(targetTime);
}
// 将时间戳转为北京时间(UTC+8)
const beijingTime = convertToTimeZone(1717251689234, 8);
console.log(beijingTime.toLocaleString());
5.4 实战:封装一个通用的时间格式化函数
javascript
/**
* 格式化时间戳
* @param {number|string} time - 时间戳(秒或毫秒)或Date对象
* @param {string} format - 格式模板,如 '{y}-{m}-{d} {h}:{i}:{s}'
* @param {number} zone - 目标时区,默认8(东八区)
*/
function parseTime(time, format = '{y}-{m}-{d} {h}:{i}:{s}', zone = 8) {
if (!time) return null;
let date;
if (typeof time === 'object') {
date = time;
} else {
// 如果是秒级时间戳(10位),转为毫秒
if (String(time).length === 10) {
time = parseInt(time) * 1000;
}
date = new Date(time);
}
// 时区调整
const utc = time + date.getTimezoneOffset() * 60000;
const wishTime = utc + 3600000 * zone;
date = new Date(wishTime);
const formatObj = {
y: date.getFullYear(),
m: date.getMonth() + 1,
d: date.getDate(),
h: date.getHours(),
i: date.getMinutes(),
s: date.getSeconds(),
a: date.getDay()
};
return format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
let value = formatObj[key];
if (key === 'a') {
return ['日', '一', '二', '三', '四', '五', '六'][value];
}
if (result.length > 0 && value < 10) {
value = '0' + value;
}
return value || 0;
});
}
// 使用示例
console.log(parseTime(Date.now(), '{y}-{m}-{d} {h}:{i}:{s}', 8));
// 输出:2024-06-01 22:21:29
这个函数参考了CSDN上常用的时间处理方案,支持秒级/毫秒级时间戳自动识别,并支持指定目标时区。
六、总结
| 要点 | 说明 |
|---|---|
| 定义 | 从1970-01-01 00:00:00 UTC到现在的秒数(或毫秒数) |
| 起点 | 1970年1月1日,源于Unix操作系统的设计选择 |
| 特性 | 绝对时间,与时区无关,全球统一 |
| JS单位 | 毫秒(注意与PHP等语言的秒区分) |
| 获取 | Date.now() / new Date().getTime() |
| 转换 | new Date(timestamp) |
| 时区处理 | toLocaleString() / Intl.DateTimeFormat |
demo链接:时间戳转换工具 - 在线工具
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)