
大多数开发者容易搞错的一件事
最常见的 Unix 时间戳错误是静默发生的:JavaScript 的 Date.now() 返回毫秒,而 Python 的 time.time() 返回秒。将 JavaScript 时间戳传递给期望秒数的 Python 函数,你会得到一个公元 33658 年的日期。这种不匹配永远不会抛出错误——它只会静默地破坏你的数据。
本指南涵盖了每种常见的时间戳操作,并提供了两种语言的可复制粘贴代码。

什么是 Unix 时间戳?
Unix 时间戳是从 1970 年 1 月 1 日 00:00:00 UTC(Unix 纪元)开始经过的秒数(或毫秒数)。它没有时区。它不代表本地时间。它是一个单一的整数,在世界上的每台计算机上都表示相同的含义。
当前时间戳:你可以通过 Unix 时间戳转换器 实时查看。
JavaScript:毫秒级时间戳
// 获取当前时间戳(毫秒)
const nowMs = Date.now(); // 例如 1717200000000
const nowMs2 = new Date().getTime(); // 相同
// 获取当前时间戳(秒——用于期望 Unix 时间的 API)
const nowSec = Math.floor(Date.now() / 1000); // 例如 1717200000
// 将时间戳转换为 Date 对象
const date = new Date(1717200000000); // 传入毫秒
console.log(date.toISOString()); // "2024-06-01T00:00:00.000Z"
// 将秒级时间戳转换为 Date(先乘以 1000!)
const fromSeconds = new Date(1717200000 * 1000);
// Date 转换为时间戳(毫秒)
const ts = new Date('2024-06-01').getTime(); // 1717200000000
// Date 转换为时间戳(秒)
const tsSec = Math.floor(new Date('2024-06-01').getTime() / 1000);

Python:秒级时间戳(浮点数)
import time
import datetime
# 获取当前时间戳(秒,浮点数)
now_sec = time.time() # 例如 1717200000.123
now_int = int(time.time()) # 整数秒
# 将时间戳转换为 datetime(UTC)
dt_utc = datetime.datetime.fromtimestamp(1717200000, tz=datetime.timezone.utc)
print(dt_utc.isoformat()) # "2024-06-01T00:00:00+00:00"
# 将时间戳转换为本地 datetime(注意夏令时)
dt_local = datetime.datetime.fromtimestamp(1717200000)
# 使用系统时区——在不同机器上行为可能不同
# datetime 转换为时间戳
dt = datetime.datetime(2024, 6, 1, tzinfo=datetime.timezone.utc)
ts = dt.timestamp() # 1717200000.0
# 当前 UTC datetime 转换为时间戳
ts_now = datetime.datetime.now(datetime.timezone.utc).timestamp()
毫秒与秒的问题
| 语言/平台 | 单位 | 示例值 |
|---|---|---|
JavaScript Date.now() |
毫秒 | 1717200000000 |
JavaScript Date.getTime() |
毫秒 | 1717200000000 |
Python time.time() |
秒(浮点数) | 1717200000.0 |
Python datetime.timestamp() |
秒(浮点数) | 1717200000.0 |
Unix shell date +%s |
秒 | 1717200000 |
MySQL UNIX_TIMESTAMP() |
秒 | 1717200000 |
Java System.currentTimeMillis() |
毫秒 | 1717200000000 |
Go time.Now().Unix() |
秒 | 1717200000 |
Go time.Now().UnixMilli() |
毫秒 | 1717200000000 |
经验法则: 如果你的时间戳是 13 位数字,则是毫秒;如果是 10 位数字,则是秒。
// 在 JavaScript 中检测并归一化
function toMilliseconds(ts) {
// 如果时间戳看起来像秒(10 位),则转换为毫秒
if (ts < 1e12) return ts * 1000;
return ts;
}

处理时区
Unix 时间戳与时区无关。复杂性在于将它们转换为人类可读的日期。
// JavaScript — 在特定时区显示
const ts = 1717200000000;
const date = new Date(ts);
// UTC
date.toISOString(); // "2024-06-01T00:00:00.000Z"
// 用户的本地时区
date.toLocaleString(); // 因系统而异
// 特定时区(Intl API)
date.toLocaleString('en-US', { timeZone: 'America/New_York' });
// "5/31/2024, 8:00:00 PM"
date.toLocaleString('en-US', { timeZone: 'Asia/Shanghai' });
// "6/1/2024, 8:00:00 AM"
# Python — 时区感知转换
import datetime
ts = 1717200000
# 始终显式使用 UTC——在服务器代码中永远不要依赖系统时区
utc = datetime.timezone.utc
dt_utc = datetime.datetime.fromtimestamp(ts, tz=utc)
# 转换为特定时区(需要 zoneinfo,Python 3.9+)
from zoneinfo import ZoneInfo
dt_ny = dt_utc.astimezone(ZoneInfo('America/New_York'))
print(dt_ny.isoformat()) # "2024-05-31T20:00:00-04:00"
计算时间差
// JavaScript — 自事件以来的时间
const eventTs = 1717200000000; // 毫秒
const now = Date.now();
const diffSeconds = Math.floor((now - eventTs) / 1000);
const diffMinutes = Math.floor(diffSeconds / 60);
const diffHours = Math.floor(diffMinutes / 60);
const diffDays = Math.floor(diffHours / 24);
// 令牌是否过期?
function isExpired(expiryTimestampSeconds) {
return Math.floor(Date.now() / 1000) > expiryTimestampSeconds;
}
# Python — 时间差
import time
import datetime
ts1 = 1717200000
ts2 = time.time()
diff_seconds = ts2 - ts1
diff_days = diff_seconds / 86400
# 使用 timedelta 获得可读的差值
dt1 = datetime.datetime.fromtimestamp(ts1, tz=datetime.timezone.utc)
dt2 = datetime.datetime.now(datetime.timezone.utc)
delta = dt2 - dt1
print(delta.days, "天,", delta.seconds // 3600, "小时")
常见陷阱
将时间戳存储为整数还是字符串: 在数据库中存储为整数,而不是字符串。将 1717200000 作为字符串比较会得到字典序,而不是时间顺序。
夏令时(DST): 当跨越本地时间的 DST 边界时,一天并不总是 86400 秒。始终在 UTC 时间戳中进行时间运算,然后格式化显示。
2038 年问题: 32 位有符号整数在 Unix 时间戳 2147483647(2038 年 1 月 19 日)处溢出。如果你在旧数据库中将时间戳存储在 32 位 INT 列中,请立即迁移到 64 位 BIGINT。
Python 中的微秒: time.time() 返回一个具有亚秒精度的浮点数。如果你需要干净的整数秒值,请使用 int(time.time())。
→ 使用 Unix 时间戳转换器 立即将任何 Unix 时间戳转换为人类可读的日期。