🕐
← 返回教程列表

在编程语言中使用 Unix 时间戳

· 标签: javascript, python, php, golang, programming, unix-timestamp, epoch, database

为什么在编程中使用 Unix 时间戳?

Unix 时间戳是软件中通用的时间货币。它们让日期运算变得简单(只需加减秒数),消除时区混乱,并能干净地序列化为 JSON。每种编程语言都提供了处理时间戳的简单函数,但这些 API 存在微妙的差异。本指南涵盖最常见的语言及其最佳实践。

JavaScript(浏览器和 Node.js)

JavaScript 的 Date 对象使用毫秒,而大多数其他系统使用秒。这是最常见的 bug 来源。

获取当前时间戳

// 自 epoch 以来的毫秒数(标准 JavaScript)
const nowMs = Date.now();         // 1785292800000

// 自 epoch 以来的秒数(用于兼容)
const nowSec = Math.floor(Date.now() / 1000);  // 1785292800

// Node.js 高分辨率计时器(微秒)
const hrTime = process.hrtime.bigint();

将时间戳转换为日期

// 从秒转换(大多数 API 和数据库)
const timestamp = 1785292800;
const date = new Date(timestamp * 1000);  // 乘以 1000!

// 从毫秒转换(JavaScript 原生)
const dateFromMs = new Date(1785292800000);

// 格式化结果
console.log(date.toISOString());
// 输出: 2026-07-19T00:00:00.000Z

console.log(date.toLocaleString("en-US", { timeZone: "America/New_York" }));
// 输出: 7/18/2026, 8:00:00 PM

将日期字符串解析为时间戳

// 使用 Date.parse()(返回毫秒)
const ms = Date.parse("2026-07-19T00:00:00Z");
const sec = ms / 1000;  // 1785292800

// 使用 Date 构造函数
const ts = Math.floor(new Date("2026-07-19 UTC").getTime() / 1000);

警告: 对于非标准的日期字符串,Date.parse() 的行为在不同浏览器之间存在差异。使用带时区说明符的 ISO 8601 格式(Z 表示 UTC)是最安全的。

在 JavaScript 中处理时区

// 在指定时区中格式化
const date = new Date(1785292800 * 1000);
const options = {
  timeZone: "Asia/Tokyo",
  year: "numeric", month: "2-digit", day: "2-digit",
  hour: "2-digit", minute: "2-digit", second: "2-digit",
};
console.log(date.toLocaleString("ja-JP", options));
// 输出: 07/19/2026 09:00:00

对于高级时区操作,推荐使用 Intl.DateTimeFormat API 或 date-fns-tzLuxon 等库。

Python

Python 提供了用于处理时间戳的底层(time)和高级(datetime)模块。

获取当前时间戳

import time

# 秒数,浮点数(包含毫秒小数部分)
current = time.time()
# 示例: 1785292800.123456

# 作为整数
current_int = int(time.time())

将时间戳转换为 datetime

from datetime import datetime

# UTC datetime(Python 3.x)
dt_utc = datetime.utcfromtimestamp(1785292800)

# 时区感知的 datetime(Python 3.9+,使用 zoneinfo)
from zoneinfo import ZoneInfo
dt_tokyo = datetime.fromtimestamp(1785292800, tz=ZoneInfo("Asia/Tokyo"))

# 格式化的字符串
print(dt_utc.strftime("%Y-%m-%d %H:%M:%S"))
# 输出: 2026-07-19 00:00:00

将日期字符串解析为时间戳

import time
from datetime import datetime

# 从日期字符串
dt = datetime.strptime("2026-07-19 00:00:00", "%Y-%m-%d %H:%M:%S")
timestamp = time.mktime(dt.timetuple())  # 按本地时间处理

# 对于 UTC 输入
from datetime import timezone
timestamp_utc = dt.replace(tzinfo=timezone.utc).timestamp()

使用 Pandas 进行数据分析

import pandas as pd

# 将一列 Unix 时间戳转换为 datetime
df["timestamp"] = pd.to_datetime(df["unix_seconds"], unit="s")

# 转换为不同的单位
df["datetime_ms"] = pd.to_datetime(df["unix_milliseconds"], unit="ms")

# 设置时区
df["timestamp_ny"] = df["timestamp"].dt.tz_localize("UTC").dt.tz_convert("America/New_York")

PHP

PHP 拥有最简单的时间戳操作 API。

获取当前时间戳

<?php
$now = time();           // 整数: 1785292800
$nowMicro = microtime();  // 字符串: "0.12345600 1785292800"
$nowFloat = microtime(true);  // 浮点数: 1785292800.1235

将时间戳转换为日期

<?php
echo date("Y-m-d H:i:s", 1785292800);
// 输出: 2026-07-19 00:00:00

// 带时区
$tz = new DateTimeZone("Europe/London");
$dt = new DateTime("@1785292800");
$dt->setTimezone($tz);
echo $dt->format("Y-m-d H:i:s");

Go

Go 的 time 包设计良好,但需要明确理解所涉及的类型。

获取当前时间戳

package main

import (
    "fmt"
    "time"
)

func main() {
    now := time.Now()
    sec := now.Unix()            // int64 秒
    milli := now.UnixMilli()     // int64 毫秒
    nano := now.UnixNano()       // int64 纳秒
    fmt.Printf("Seconds: %d\n", sec)
}

将时间戳转换为日期

t := time.Unix(1785292800, 0)
fmt.Println(t.UTC())
// 输出: 2026-07-19 00:00:00 +0000 UTC

// 格式化为字符串
fmt.Println(t.Format("2006-01-02 15:04:05"))
// 输出: 2026-07-19 00:00:00

// 带时区
loc, _ := time.LoadLocation("America/Chicago")
fmt.Println(t.In(loc))

Rust

use std::time::{SystemTime, UNIX_EPOCH};

// 当前时间戳
let now = SystemTime::now()
    .duration_since(UNIX_EPOCH)
    .expect("Time went backwards");
println!("Seconds: {}", now.as_secs());

// 时间戳转日期
let dt = chrono::NaiveDateTime::from_timestamp_opt(1785292800, 0).unwrap();
println!("{}", dt.format("%Y-%m-%d %H:%M:%S"));

数据库存储:最佳实践

选择正确的列类型

| 数据库 | 推荐类型 | 说明 | |----------|-----------------|-------| | PostgreSQL | TIMESTAMP WITH TIME ZONEBIGINT | 优先使用原生时间戳类型 | | MySQL / MariaDB | INT UNSIGNED(适用于 2106 年之前的日期)或 BIGINT | 避免使用 TIMESTAMP 类型(范围止于 2038 年) | | SQLite | INTEGER | SQLite 没有原生时间戳类型 | | MongoDB | Date 对象或 int64 | BSON Date 内部就是一个 64 位时间戳 |

PostgreSQL 示例

-- 以原生时间戳存储
CREATE TABLE events (
    id SERIAL PRIMARY KEY,
    occurred_at TIMESTAMP WITH TIME ZONE NOT NULL,
    payload JSONB
);

-- 使用当前时间插入
INSERT INTO events (occurred_at) VALUES (NOW());

-- 以 Unix 时间戳查询
SELECT EXTRACT(EPOCH FROM occurred_at) AS unix_ts FROM events;

MySQL 示例

-- 使用 BIGINT 进行面向未来的存储
CREATE TABLE logs (
    id INT AUTO_INCREMENT PRIMARY KEY,
    event_time BIGINT NOT NULL,
    message TEXT
);

-- 插入当前时间戳
INSERT INTO logs (event_time, message) VALUES (UNIX_TIMESTAMP(), 'Server started');

-- 查询并转换
SELECT FROM_UNIXTIME(event_time) AS readable_time FROM logs;

语言对比表

| 语言 | 当前时间戳 | 时间戳转日期 | 日期转时间戳 | 分辨率 | |----------|-------------------|-------------------|-------------------|------------| | JavaScript | Date.now() | new Date(ts * 1000) | Date.parse(str) / 1000 | 毫秒 | | Python | time.time() | datetime.fromtimestamp(ts) | datetime.strptime(str).timestamp() | 浮点秒 | | PHP | time() | date("Y-m-d", ts) | strtotime(str) | 秒 | | Go | time.Now().Unix() | time.Unix(ts, 0) | time.Parse(layout, str).Unix() | 秒 | | Rust | SystemTime::now() | NaiveDateTime::from_timestamp_opt() | — | 多种 |

无论你使用哪种语言,我们的 Unix 时间戳转换器 都是快速检查和调试时可靠的辅助工具。