在程式語言中使用 Unix 時間戳
為什麼在程式設計中使用 Unix 時間戳?
Unix 時間戳是軟體中通用的時間貨幣。它們讓日期運算變得簡單(只需加減秒數)、消除時區混淆,並且能乾淨地序列化為 JSON。每種程式語言都提供了直接的函數來處理它們,但 API 略有不同。本指南涵蓋最常見的語言及其最佳實踐。
JavaScript(瀏覽器和 Node.js)
JavaScript 的 Date 物件使用毫秒,而大多數其他系統使用秒。這是最常見的錯誤來源。
獲取當前時間戳
// 自紀元以來的毫秒數(標準 JavaScript)
const nowMs = Date.now(); // 1785292800000
// 自紀元以來的秒數(用於相容性)
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() 的行為在不同瀏覽器中可能不同。使用附帶時區標識符(Z 表示 UTC)的 ISO 8601 格式最安全。
在 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-tz、Luxon 等程式庫。
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 ZONE 或 BIGINT | 優先使用原生時間戳類型 |
| 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 時間戳轉換器 都是快速檢查和除錯的可靠夥伴。