🕐
← 返回教學列表

在程式語言中使用 Unix 時間戳

· 標籤: javascript, python, php, golang, programming, unix-timestamp, epoch, database

為什麼在程式設計中使用 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-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 時間戳轉換器 都是快速檢查和除錯的可靠夥伴。