Unix 时间戳(也称 Epoch 时间或 POSIX 时间)是计算机中最通用的时间表示方式之一。本指南将展示如何在 JavaScript、Python、Bash、SQL、PHP 和 Go 中将 Unix 时间戳转换为可读日期,附带可直接复制的代码示例。
1. 什么是 Unix 时间戳?
Unix 时间戳是从 1970 年 1 月 1 日 00:00:00 UTC(即 Unix 纪元)起经过的秒数。它是一个整数,可以无歧义地表示一个时间点,不受时区影响。
某些系统(特别是 JavaScript 和 Java)使用毫秒而非秒。毫秒时间戳是秒的 1000 倍,例如:1700000000(秒)vs 1700000000000(毫秒)。
关键特性:Unix 时间戳始终是 UTC 时间,始终是整数(或浮点数用于亚秒精度),始终从同一纪元开始计数。负值表示 1970 年之前的日期。
Unix Epoch: January 1, 1970 00:00:00 UTC
Timestamp: 0
Current: ~1700000000 (November 2023)
= 1,700,000,000 seconds since epoch
In milliseconds: 1700000000000 (13 digits)
In seconds: 1700000000 (10 digits)2. JavaScript:new Date()、toISOString()、Intl.DateTimeFormat
JavaScript 的 Date 构造函数接受毫秒时间戳。如果你有秒级 Unix 时间戳,需要先乘以 1000。
基本转换(秒转日期)
const timestamp = 1700000000; // seconds
// Convert to Date object (multiply by 1000 for milliseconds)
const date = new Date(timestamp * 1000);
console.log(date);
// Tue Nov 14 2023 22:13:20 GMT+0000 (UTC)
console.log(date.toUTCString());
// "Tue, 14 Nov 2023 22:13:20 GMT"
console.log(date.toLocaleDateString());
// "11/14/2023" (varies by locale)ISO 8601 字符串
const timestamp = 1700000000;
const date = new Date(timestamp * 1000);
console.log(date.toISOString());
// "2023-11-14T22:13:20.000Z"
// Parse back to timestamp
const parsed = Date.parse("2023-11-14T22:13:20.000Z");
console.log(parsed / 1000);
// 1700000000使用 Intl.DateTimeFormat 进行本地化格式化
const timestamp = 1700000000;
const date = new Date(timestamp * 1000);
// US English
const usFormat = new Intl.DateTimeFormat('en-US', {
dateStyle: 'full',
timeStyle: 'long',
timeZone: 'America/New_York'
}).format(date);
// "Tuesday, November 14, 2023 at 5:13:20 PM EST"
// Japanese
const jpFormat = new Intl.DateTimeFormat('ja-JP', {
dateStyle: 'full',
timeStyle: 'long',
timeZone: 'Asia/Tokyo'
}).format(date);
// "2023年11月15日水曜日 7:13:20 JST"
// Chinese
const cnFormat = new Intl.DateTimeFormat('zh-CN', {
year: 'numeric', month: '2-digit', day: '2-digit',
hour: '2-digit', minute: '2-digit', second: '2-digit',
timeZone: 'Asia/Shanghai'
}).format(date);
// "2023/11/15 06:13:20"提取日期各部分
const timestamp = 1700000000;
const date = new Date(timestamp * 1000);
const year = date.getUTCFullYear(); // 2023
const month = date.getUTCMonth() + 1; // 11 (0-indexed, so +1)
const day = date.getUTCDate(); // 14
const hours = date.getUTCHours(); // 22
const mins = date.getUTCMinutes(); // 13
const secs = date.getUTCSeconds(); // 20
// Get current timestamp
const now = Math.floor(Date.now() / 1000);3. Python:datetime.fromtimestamp(),时区感知
Python 的 datetime 模块提供了简洁的时间戳转换。始终使用时区感知方法以避免歧义。
基本转换
from datetime import datetime
timestamp = 1700000000
# Basic conversion (returns local time!)
dt = datetime.fromtimestamp(timestamp)
print(dt)
# 2023-11-14 22:13:20 (in your local timezone)
# Format as string
print(dt.strftime("%Y-%m-%d %H:%M:%S"))
# "2023-11-14 22:13:20"时区感知(推荐)
from datetime import datetime, timezone
timestamp = 1700000000
# UTC (recommended approach)
dt_utc = datetime.fromtimestamp(timestamp, tz=timezone.utc)
print(dt_utc)
# 2023-11-14 22:13:20+00:00
print(dt_utc.isoformat())
# "2023-11-14T22:13:20+00:00"
# Get current UTC timestamp
import time
current_ts = int(time.time())
print(current_ts)转换到其他时区
from datetime import datetime, timezone
from zoneinfo import ZoneInfo # Python 3.9+
timestamp = 1700000000
# Convert to Tokyo time
tokyo = datetime.fromtimestamp(timestamp, tz=ZoneInfo("Asia/Tokyo"))
print(tokyo)
# 2023-11-15 07:13:20+09:00
# Convert to New York time
ny = datetime.fromtimestamp(timestamp, tz=ZoneInfo("America/New_York"))
print(ny)
# 2023-11-14 17:13:20-05:00
# Convert to Shanghai time
shanghai = datetime.fromtimestamp(timestamp, tz=ZoneInfo("Asia/Shanghai"))
print(shanghai)
# 2023-11-15 06:13:20+08:00毫秒时间戳
from datetime import datetime, timezone
ms_timestamp = 1700000000000 # 13 digits = milliseconds
# Divide by 1000 to get seconds
dt = datetime.fromtimestamp(ms_timestamp / 1000, tz=timezone.utc)
print(dt)
# 2023-11-14 22:13:20+00:004. Bash/Shell:date -d @timestamp、macOS date -r
Linux 和 macOS 的 date 命令语法不同。以下是两种方式。
Linux(GNU date)
# Linux (GNU coreutils date)
date -d @1700000000
# Tue Nov 14 22:13:20 UTC 2023
# With UTC explicitly
date -u -d @1700000000
# Tue Nov 14 22:13:20 UTC 2023
# ISO 8601 format
date -d @1700000000 --iso-8601=seconds
# 2023-11-14T22:13:20+00:00macOS(BSD date)
# macOS (BSD date) - uses -r instead of -d @
date -r 1700000000
# Tue Nov 14 22:13:20 UTC 2023
# With UTC
date -u -r 1700000000
# Tue Nov 14 22:13:20 UTC 2023获取当前 Unix 时间戳
# Works on both Linux and macOS
date +%s
# 1700000000 (current timestamp in seconds)
# Milliseconds (Linux)
date +%s%N | cut -b1-13
# Milliseconds (macOS with Python)
python3 -c "import time; print(int(time.time() * 1000))"自定义格式
# Linux
date -d @1700000000 "+%Y-%m-%d %H:%M:%S"
# 2023-11-14 22:13:20
# macOS
date -r 1700000000 "+%Y-%m-%d %H:%M:%S"
# 2023-11-14 22:13:20
# Common format specifiers:
# %Y = 4-digit year %m = month (01-12)
# %d = day (01-31) %H = hour (00-23)
# %M = minute (00-59) %S = second (00-59)
# %Z = timezone name %z = timezone offset5. SQL:MySQL、PostgreSQL、SQLite
每个主流 SQL 数据库都有内置函数在 Unix 时间戳和日期之间转换。
MySQL:FROM_UNIXTIME()
-- MySQL: Convert timestamp to datetime
SELECT FROM_UNIXTIME(1700000000);
-- '2023-11-14 22:13:20'
-- With custom format
SELECT FROM_UNIXTIME(1700000000, '%Y-%m-%d %H:%i:%s');
-- '2023-11-14 22:13:20'
-- In a query
SELECT id, name, FROM_UNIXTIME(created_at) AS created_date
FROM users
WHERE created_at > UNIX_TIMESTAMP('2023-01-01');PostgreSQL:to_timestamp()
-- PostgreSQL: Convert timestamp to date
SELECT to_timestamp(1700000000);
-- '2023-11-14 22:13:20+00'
-- With timezone
SELECT to_timestamp(1700000000) AT TIME ZONE 'America/New_York';
-- '2023-11-14 17:13:20'
-- Format output
SELECT to_char(to_timestamp(1700000000), 'YYYY-MM-DD HH24:MI:SS');
-- '2023-11-14 22:13:20'SQLite:datetime()
-- SQLite: Convert timestamp to datetime string
SELECT datetime(1700000000, 'unixepoch');
-- '2023-11-14 22:13:20'
-- In local time
SELECT datetime(1700000000, 'unixepoch', 'localtime');
-- '2023-11-14 17:13:20' (depends on server timezone)
-- With strftime
SELECT strftime('%Y-%m-%d %H:%M:%S', 1700000000, 'unixepoch');
-- '2023-11-14 22:13:20'反向:日期转 Unix 时间戳
-- MySQL: Date to Unix timestamp
SELECT UNIX_TIMESTAMP('2023-11-14 22:13:20');
-- 1700000000
-- PostgreSQL: Date to Unix timestamp
SELECT EXTRACT(EPOCH FROM TIMESTAMP '2023-11-14 22:13:20');
-- 1700000000
-- SQLite: Date to Unix timestamp
SELECT strftime('%s', '2023-11-14 22:13:20');
-- '1700000000'6. PHP:date()、Carbon
PHP 有出色的内置日期/时间函数,以及流行的 Carbon 库提供更具表达力的代码。
内置 date()
<?php
$timestamp = 1700000000;
// Basic date() function
echo date('Y-m-d H:i:s', $timestamp);
// "2023-11-14 22:13:20"
// ISO 8601
echo date('c', $timestamp);
// "2023-11-14T22:13:20+00:00"
// RFC 2822 (email headers)
echo date('r', $timestamp);
// "Tue, 14 Nov 2023 22:13:20 +0000"
// Current timestamp
echo time();
// current Unix timestamp in secondsDateTime 类
<?php
$timestamp = 1700000000;
// DateTime class (more flexible)
$dt = new DateTime("@$timestamp");
$dt->setTimezone(new DateTimeZone('UTC'));
echo $dt->format('Y-m-d H:i:s T');
// "2023-11-14 22:13:20 UTC"
// Convert to other timezone
$dt->setTimezone(new DateTimeZone('Asia/Shanghai'));
echo $dt->format('Y-m-d H:i:s T');
// "2023-11-15 06:13:20 CST"
// DateTimeImmutable (thread-safe)
$dti = (new DateTimeImmutable("@$timestamp"))
->setTimezone(new DateTimeZone('America/New_York'));
echo $dti->format('Y-m-d H:i:s T');
// "2023-11-14 17:13:20 EST"Carbon 库(Laravel)
<?php
use Carbon\Carbon;
$timestamp = 1700000000;
// Carbon (popular in Laravel)
$date = Carbon::createFromTimestamp($timestamp);
echo $date->toDateTimeString();
// "2023-11-14 22:13:20"
echo $date->diffForHumans();
// "X months ago"
echo $date->timezone('Asia/Tokyo')->format('Y-m-d H:i:s');
// "2023-11-15 07:13:20"
// From milliseconds
$ms = Carbon::createFromTimestampMs(1700000000000);7. Go:time.Unix()
Go 的 time 包提供了 Unix() 函数进行简洁的时间戳转换。
基本转换
package main
import (
"fmt"
"time"
)
func main() {
timestamp := int64(1700000000)
// Convert seconds to time.Time
t := time.Unix(timestamp, 0)
fmt.Println(t.UTC())
// 2023-11-14 22:13:20 +0000 UTC
fmt.Println(t.UTC().String())
// "2023-11-14 22:13:20 +0000 UTC"
}自定义格式化
package main
import (
"fmt"
"time"
)
func main() {
t := time.Unix(1700000000, 0).UTC()
// Go uses a reference time: Mon Jan 2 15:04:05 MST 2006
fmt.Println(t.Format("2006-01-02 15:04:05"))
// "2023-11-14 22:13:20"
fmt.Println(t.Format(time.RFC3339))
// "2023-11-14T22:13:20Z"
fmt.Println(t.Format(time.RFC1123))
// "Tue, 14 Nov 2023 22:13:20 UTC"
// With timezone
loc, _ := time.LoadLocation("Asia/Tokyo")
fmt.Println(t.In(loc).Format("2006-01-02 15:04:05 MST"))
// "2023-11-15 07:13:20 JST"
// Get current timestamp
now := time.Now().Unix()
fmt.Println(now)
}毫秒时间戳
package main
import (
"fmt"
"time"
)
func main() {
msTimestamp := int64(1700000000000) // milliseconds
// Unix() takes (seconds, nanoseconds)
t := time.Unix(0, msTimestamp*int64(time.Millisecond))
fmt.Println(t.UTC())
// 2023-11-14 22:13:20 +0000 UTC
// Or divide by 1000
t2 := time.Unix(msTimestamp/1000, 0)
fmt.Println(t2.UTC())
// 2023-11-14 22:13:20 +0000 UTC
}8. 毫秒 vs 秒:如何识别和转换
处理时间戳时最常见的 Bug 之一就是混淆秒和毫秒。以下是区分和转换方法。
- 秒级时间戳通常是 10 位数字(如
1700000000),表示 2020 年代的日期。 - 毫秒时间戳通常是 13 位数字(如
1700000000000)。 - 如果时间戳产生了公元 50000 年以后的日期,你可能把毫秒传给了期望秒的函数。
- 如果时间戳产生了 1970 年 1 月的日期,你可能把秒传给了期望毫秒的函数。
快速转换公式
// Detect: count digits
function isMilliseconds(ts) {
return ts.toString().length >= 13;
}
// Seconds to milliseconds
const ms = seconds * 1000;
// Milliseconds to seconds
const sec = Math.floor(milliseconds / 1000);
// Auto-detect and normalize to seconds
function toSeconds(ts) {
return ts > 9999999999 ? Math.floor(ts / 1000) : ts;
}
// Python equivalent
def to_seconds(ts):
return ts // 1000 if ts > 9999999999 else ts9. 值得关注的 Unix 时间戳
一些 Unix 时间戳在计算机历史和未来中具有特殊意义。
| 时间戳 | 日期(UTC) | 意义 |
|---|---|---|
0 | 1970-01-01 00:00:00 | Unix 纪元(起点) |
-14182940 | 1969-07-20 20:17:40 | 人类登月(负时间戳) |
946684800 | 2000-01-01 00:00:00 | 千年虫(Y2K,2000年) |
1000000000 | 2001-09-09 01:46:40 | 第 10 亿秒 |
2000000000 | 2033-05-18 03:33:20 | 第 20 亿秒 |
2147483647 | 2038-01-19 03:14:07 | 32 位溢出(2038 年问题) (有符号 32 位整数最大值) |
# Verify notable timestamps yourself:
# Bash (Linux)
date -u -d @0 # Thu Jan 1 00:00:00 UTC 1970
date -u -d @946684800 # Sat Jan 1 00:00:00 UTC 2000
date -u -d @2147483647 # Tue Jan 19 03:14:07 UTC 2038
# Python
from datetime import datetime, timezone
datetime.fromtimestamp(2147483647, tz=timezone.utc)
# datetime(2038, 1, 19, 3, 14, 7, tzinfo=timezone.utc)
# JavaScript
new Date(2147483647 * 1000).toISOString()
// "2038-01-19T03:14:07.000Z"10. 时区陷阱:UTC vs 本地时间
时区处理是时间戳相关 Bug 的头号来源。以下是需要记住的关键规则。
- Unix 时间戳始终是 UTC。不存在"本地" Unix 时间戳。
- 在 JavaScript 中调用
new Date(ts * 1000)时,Date 对象内部存储 UTC,但.toString()会以用户的本地时区显示。 - Python 的
datetime.fromtimestamp()默认返回本地时间。使用datetime.fromtimestamp(ts, tz=timezone.utc)获取 UTC。 - 始终以 UTC 存储时间戳,仅在显示时转换为本地时间。
- 注意夏令时(DST)转换。同一本地时间可能出现两次(秋季回拨)或完全不存在(春季前拨)。
JavaScript:UTC vs 本地输出对比
const timestamp = 1700000000;
const date = new Date(timestamp * 1000);
// These are DIFFERENT if you're not in UTC:
console.log(date.toString());
// "Tue Nov 14 2023 17:13:20 GMT-0500 (Eastern Standard Time)"
// ^ Local time
console.log(date.toUTCString());
// "Tue, 14 Nov 2023 22:13:20 GMT"
// ^ UTC time
console.log(date.toISOString());
// "2023-11-14T22:13:20.000Z"
// ^ Always UTC (the Z means Zulu/UTC)
// Safe: always use UTC methods
console.log(date.getUTCHours()); // 22 (UTC)
console.log(date.getHours()); // 17 (local, if EST)# Python timezone comparison
from datetime import datetime, timezone
from zoneinfo import ZoneInfo
ts = 1700000000
# WRONG: naive datetime (no timezone info)
naive = datetime.fromtimestamp(ts)
print(naive) # ambiguous - depends on server timezone
# RIGHT: timezone-aware
utc = datetime.fromtimestamp(ts, tz=timezone.utc)
print(utc) # 2023-11-14 22:13:20+00:00
# Convert between zones safely
eastern = utc.astimezone(ZoneInfo("America/New_York"))
print(eastern) # 2023-11-14 17:13:20-05:00
# The underlying timestamp is always the same
print(utc.timestamp() == eastern.timestamp()) # True常见问题
什么是 Unix 时间戳?
Unix 时间戳(也称 Epoch 时间或 POSIX 时间)是从 1970 年 1 月 1 日 00:00:00 UTC 起经过的秒数。它是一种不依赖时区的方式,用一个整数表示特定的时间点。
为什么 JavaScript 使用毫秒而不是秒?
JavaScript 的 Date 对象设计上与 Java 的 java.util.Date 一致,使用毫秒以获得更高精度。在 JavaScript 中处理 Unix 时间戳时,始终将秒乘以 1000:new Date(timestamp * 1000)。
什么是 2038 年问题?
将 Unix 时间戳存储为有符号 32 位整数的系统将在 2038 年 1 月 19 日 03:14:07 UTC 发生溢出,届时值超过 2,147,483,647。时间戳将变为负数,导致日期跳回 1901 年。大多数现代系统已使用 64 位整数,不会在 2920 亿年内溢出。
如何获取当前 Unix 时间戳?
JavaScript:Math.floor(Date.now() / 1000)。Python:import time; int(time.time())。Bash:date +%s。PHP:time()。Go:time.Now().Unix()。都返回 UTC 自纪元以来的秒数。
Unix 时间戳可以是负数吗?
可以。负 Unix 时间戳表示 1970 年 1 月 1 日之前的日期。例如,-1 表示 1969 年 12 月 31 日 23:59:59 UTC。1969 年 7 月 20 日的人类登月时间戳为 -14182940。大多数现代语言和数据库都能正确处理负时间戳。