← 返回工具首页

时间戳转换完全指南:从入门到精通

凌晨三点,你被生产环境的告警叫醒。日志里有一串莫名其妙的数字——1715164800000。这是什么时候?你对着屏幕发呆了两秒,然后开始怀疑人生。如果你有过这种经历,那这篇文章就是为你写的。

时间戳是后端开发中最容易被忽视、却最容易出问题的细节之一。10位还是13位?毫秒还是秒?UTC还是本地时区?每一个选择都可能埋雷。本文用五分钟,让你把时间戳彻底学明白。

一、痛点场景:为什么你总在这里翻车

先说几个真实发生过的案例,感受一下时间戳的杀伤力。

场景一:前后端对不上
前端传来1715164800,后端以为这是秒,转成北京时间是2024-05-08 16:00:00。但前端实际上传的是毫秒timestamp,正确时间应该是2024-05-09 00:00:00。8小时的差距,线上已经跑了两周才发现。

场景二:数据库里存的两个时间戳,差了1000倍
MySQL里一列是毫秒级的BIGINT,另一列是秒级的INT,JOIN的时候一脸懵。最坑的是两个字段都有索引,都很慢,就是不知道差了一千倍。

场景三:时区混乱
服务器在美国,代码在本地,数据库在上海。存进去的时间戳是对的,展示出来的时间永远是错的。三方SDK返回的时间戳有的是UTC,有的是本地时间,你根本不知道该信谁。

这些问题每年在无数团队里反复上演。根源在于:时间戳没有标准,每个系统各搞各的。但只要你理解了原理,这些坑完全可以避免。

二、Unix时间戳究竟是什么

Unix时间戳(Unix Timestamp)是自1970年1月1日 00:00:00 UTC以来经过的秒数(或者毫秒数)。这是一切的起点,被称为"Unix纪元"(Epoch)。

举几个例子:

为什么1970年?因为Unix系统最早是在1970年代被开发出来的,这个时间点被作为基准,沿用至今,成了行业共识。

时间戳的核心优势就三个字:可计算。字符串日期没法做减法,但时间戳是整数,直接加减就能得到时间差。数据库索引、缓存过期、任务调度,全靠这个。

三、10位 vs 13位:毫秒与秒的战争

这是最容易踩的坑,没有之一。

10位时间戳:单位是秒(seconds)。这是最传统的Unix时间戳格式,大多数Linux系统默认使用。

13位时间戳:单位是毫秒(milliseconds)。JavaScript的Date.now()、Java的System.currentTimeMillis()默认返回这个格式。前端领域几乎全部用毫秒级时间戳。

换算关系13位 = 10位 * 1000

举例说明:

10位: 1715164800  (秒)   → 2024-05-08 16:00:00 UTC
13位: 1715164800000 (毫秒) → 2024-05-08 16:00:00 UTC

如果你在日志里看到一串13位数字,第一反应应该是"毫秒",不要下意识当秒来处理。

如何判断一个时间戳是秒还是毫秒?

一个粗暴但有效的经验:

但更可靠的方法是:问清楚数据来源。JavaScript和Java默认毫秒,Python和Go默认秒,Linux的date +%s默认秒。记住这个对应关系,能少走很多弯路。

四、各语言获取时间戳的方法

JavaScript / 前端

// 获取当前时间戳(毫秒)
const ms = Date.now();          // 1715164800000

// 获取当前时间戳(秒)—— 需要 /1000
const s = Math.floor(Date.now() / 1000); // 1715164800

// 时间戳转 Date 对象
new Date(1715164800000);         // Thu May 09 2024 00:00:00 GMT+0800

// Date 对象转时间戳
new Date().getTime();            // 等同于 Date.now()
+new Date();                     // 隐式转换,效果相同

Python

import time

# 当前时间戳(秒)
s = time.time()                 # 1715164800.123

# 整型时间戳(秒)
int(time.time())                # 1715164800

# 当前时间戳(毫秒)
import time
ms = int(time.time() * 1000)    # 1715164800123

# 时间戳 → datetime
from datetime import datetime
dt = datetime.fromtimestamp(1715164800)
print(dt)                       # 2024-05-09 00:00:00

# datetime → 时间戳
ts = int(dt.timestamp())        # 1715164800

Java

// 当前时间戳(毫秒)
long ms = System.currentTimeMillis(); // 1715164800123

// 当前时间戳(秒)
long s = System.currentTimeMillis() / 1000; // 1715164800

// 时间戳 → Date
Date date = new Date(1715164800000L);

// Date → 时间戳
long ts = date.getTime(); // 1715164800000

// Instant(Java 8+ 推荐方式)
Instant now = Instant.now();
long ts = now.toEpochMilli();    // 毫秒
long s = now.getEpochSecond();   // 秒

Go

package main

import (
    "time"
)

func main() {
    // 当前时间戳(秒)
    s := time.Now().Unix() // 1715164800

    // 当前时间戳(毫秒)
    ms := time.Now().UnixMilli() // 1715164800123

    // 时间戳 → Time
    t := time.Unix(1715164800, 0)

    // 毫秒时间戳 → Time
    t2 := time.UnixMilli(1715164800123)

    println(t.Format("2006-01-02 15:04:05"))
}

Node.js(后端)

// 获取当前时间戳(毫秒)
const ms = Date.now();

// 获取当前时间戳(秒)
const s = Math.floor(Date.now() / 1000);

// 时间戳转 Date
const date = new Date(1715164800000);

// Date 转时间戳
const ts = date.getTime();

// Unix 纳秒级(极少用)
const ns = process.hrtime.bigint(); // 1715164800123456789n

Bash / Linux 命令行

# 获取当前时间戳(秒)
date +%s

# 毫秒级时间戳
date +%s%3N

# 时间戳 → 可读时间
date -d @1715164800

# 可读时间 → 时间戳
date -d "2024-05-09 00:00:00" +%s

五、时区转换:最容易被忽视的一环

时区问题是时间戳世界里最脏的角落。大多数人以为时间戳是"绝对时间",不存在时区问题。这话只对了一半。

时间戳本身确实是绝对的——1715164800在全球任何角落都代表同一个瞬间。但把这个时间戳转成人能看懂的时间,就一定涉及时区。

举一个经典错误:

// 北京时间 2024-05-09 00:00:00
// 错误做法
new Date(1715164800); // UTC时间,不是北京时间

// 正确做法
new Date(1715164800 * 1000); // 乘以1000转毫秒

// 正确显示北京时间
new Date(1715164800 * 1000).toLocaleString('zh-CN', {
    timeZone: 'Asia/Shanghai'
});

在中国做开发,默认时区通常是Asia/Shanghai(东八区,UTC+8)。但服务器可能跑在美国(UTC-xx),或者Docker容器里是UTC。你的代码必须明确指定时区,不能依赖系统默认值。

时区转换的几个关键操作:

实际代码中建议使用专业的时区库,避免自己算偏移量:

# Python 时区转换示例
from datetime import datetime
import pytz

beijing = pytz.timezone('Asia/Shanghai')
dt = datetime.now(beijing)
print(dt.timestamp()) # 输出北京时间对应的时间戳

# Python 3.9+ 推荐用法
from zoneinfo import ZoneInfo
dt = datetime.now(ZoneInfo('Asia/Shanghai'))
// Go 时区转换
loc, _ := time.LoadLocation("Asia/Shanghai")
t := time.Now().In(loc)
fmt.Println(t.Unix()) // 北京时间对应的时间戳

六、常见错误与避坑指南

错误一:JavaScript时间戳当秒用

Date.now()返回的是毫秒,直接传给后端时会是个13位数字。如果后端按秒来处理,就会得到一个"未来时间"——因为1715164800000秒约等于54000年后。解决方案:前后端约定好单位,或者统一用毫秒,并在文档里写清楚。

错误二:MySQL存储时间戳用了INT

INT最大只能存2147483647,对应的时间上限是2038-01-19 11:14:07 UTC。这就是著名的"2038问题"。如果你的系统需要存较远的时间,用BIGINT存毫秒级时间戳,或者直接用MySQL的DATETIME类型。

错误三:跨时区比较时间戳

两个不同服务器产生的时间戳不能直接比较时间差,因为它们的本地时钟可能基于不同的时区。正确做法:统一转成UTC或Unix时间戳再比较,绝对不做字符串日期的比较。

错误四:夏令时导致的时间偏移

美国东部时间在夏令时期间是UTC-4,非夏令时是UTC-5。如果你的时区逻辑没考虑夏令时,每年会有两次时间出现奇怪的跳变。解决方案:用IANA时区数据库(如Asia/ShanghaiAmerica/New_York),不要用固定偏移量。

错误五:日志里存了本地时间,但没有时区信息

日志里写了2024-05-09 00:00:00,但没有标注时区。这在跨时区排查问题时是灾难。建议日志时间全部用UTC,或者存成时间戳 + 时区字符串两种格式。

七、工具推荐:在线时间戳转换

日常开发中,最高效的方式是使用在线工具。推荐使用:

时间戳转换工具 - 山夜工具站

功能包括:

收藏这个链接,开发效率直接翻倍。遇到时间戳问题,不用写代码,直接打开工具秒查。

总结

时间戳的核心就三句话:

记住这三点,你就能躲开90%的时间戳相关bug。省下来的时间,足够你多写两倍的功能。

遇到时间戳问题,先别急着写代码,打开工具站查一下,有时候比调试代码还快。

💡 遇到同类问题?用工具快速解决

试试这些配套工具,无需注册,打开即用

时间戳转换

常见问题

Q: 如何使用 时间戳转换完全指南 相关工具?
A: 这类工具一般有明确的输入框和输出框,按提示输入内容,点击对应按钮即可得到结果。建议先用简单示例测试功能是否正常,再处理实际数据。
Q: 时间戳转换完全指南 适合在什么场景使用?
A: 根据具体工具类型决定。格式转换工具适合处理第三方数据,编码工具适合加密传输,压缩工具适合文件上传前处理。多积累工具使用经验,遇到问题时能快速判断用哪个工具解决。
Q: 有没有更好的替代工具?
A: 不同工具有不同侧重,重点是理解原理。可以同时安装多个类似工具,实际使用中对比效果,选择最顺手的一个。随着使用经验增加,你也能判断工具的好坏。