本文 AI 產出,尚未審核
JavaScript 日期與時間(Date & Time)─ 取得與設定時間
簡介
在前端開發或 Node.js 後端程式中,時間的處理是最常見也最容易出錯的需求。不論是顯示使用者的最後登入時間、計算兩筆資料的相差天數,或是製作倒數計時器,都離不開 Date 物件。
本單元聚焦於 取得與設定時間 的基本操作,讓你能快速抓取現在的時間、拆解成年、月、日、時、分、秒,並且依需求自行調整。掌握這些技巧後,你就能在專案中正確處理時區、毫秒級的計算,並避免常見的時間錯誤。
核心概念
1. 建立 Date 物件
// 取得目前時間(本機時區)
const now = new Date(); // => 2025-11-20T07:30:45.123Z(ISO 格式)
new Date()會回傳一個 代表當前時間的Date物件。- 若傳入字串、數字或其他
Date物件,可建立對應的時間點。
// 以字串建立(ISO 8601)
const utc = new Date('2025-01-01T00:00:00Z');
// 以毫秒數(Unix epoch)建立
const fromEpoch = new Date(0); // 1970-01-01T00:00:00.000Z
2. 取得時間資訊
| 方法 | 說明 | 範例 |
|---|---|---|
getFullYear() |
取得四位數的年份 | now.getFullYear() → 2025 |
getMonth() |
取得月份(0~11,0 為一月) | now.getMonth() → 10(11 月) |
getDate() |
取得月份中的日期(1~31) | now.getDate() → 20 |
getHours()、getMinutes()、getSeconds()、getMilliseconds() |
取得時、分、秒、毫秒 | now.getHours() → 7 |
getDay() |
取得星期幾(0~6,0 為星期日) | now.getDay() → 4(星期四) |
getTime() |
取得自 1970-01-01 UTC 起的毫秒數 | now.getTime() → 1732085445123 |
小技巧:如果需要 UTC 時間,使用
getUTCFullYear()、getUTCMonth()等對應方法。
// 取得現在的完整時間字串(本機時區)
const formatted = `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()} ` +
`${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}`;
console.log(formatted); // 2025-11-20 7:30:45
3. 設定時間資訊
Date 物件是 可變的(mutable),可以直接修改其內部時間。
const d = new Date(); // 現在時間
d.setFullYear(2024); // 改成 2024 年
d.setMonth(0); // 改成 1 月(0 代表一月)
d.setDate(15); // 改成 15 日
d.setHours(23, 59, 59, 999); // 同時設定時、分、秒、毫秒
console.log(d.toISOString()); // 2024-01-15T23:59:59.999Z(假設時區為 UTC)
setFullYear(year [, month [, day]])、setMonth(month [, day])、setDate(day)等方法都支援 多參數,一次設定多個欄位。- 設定值超出正常範圍時,
Date會自動 進位或退位(例如setMonth(12)會跳到下一年的一月)。
const overflow = new Date(2025, 0, 31); // 2025-01-31
overflow.setDate(32); // 超過當月天數,會變成 2025-02-01
console.log(overflow.toDateString()); // Sun Feb 01 2025
4. 以毫秒為基礎的運算
因為 Date 內部以 UTC 毫秒 儲存,進行時間差或加減時,直接操作毫秒最直觀。
const start = new Date(); // 開始時間
// 兩小時後的時間
const twoHoursLater = new Date(start.getTime() + 2 * 60 * 60 * 1000);
console.log(twoHoursLater.toLocaleString());
// 計算兩個日期的天數差
function diffInDays(a, b) {
const msPerDay = 24 * 60 * 60 * 1000;
return Math.round(Math.abs(a - b) / msPerDay);
}
console.log(diffInDays(new Date('2025-12-01'), new Date('2025-11-20'))); // 11
程式碼範例
範例 1️⃣:取得現在的本地時間與 UTC 時間
// 本機時間
const local = new Date();
console.log('本機時間:', local.toString());
// UTC 時間
console.log('UTC 時間:', local.toUTCString());
// 只取出時間部份(HH:MM:SS)
const timeStr = `${local.getHours().toString().padStart(2, '0')}:` +
`${local.getMinutes().toString().padStart(2, '0')}:` +
`${local.getSeconds().toString().padStart(2, '0')}`;
console.log('現在時間(HH:MM:SS):', timeStr);
重點:
toString()依本機時區呈現,toUTCString()則固定為 UTC。
範例 2️⃣:自訂生日倒數計時(天、時、分、秒)
function countdown(target) {
const now = new Date();
const diff = target - now; // 毫秒差
if (diff <= 0) return '生日快樂 🎉';
const days = Math.floor(diff / (24*60*60*1000));
const hours = Math.floor((diff % (24*60*60*1000)) / (60*60*1000));
const minutes = Math.floor((diff % (60*60*1000)) / (60*1000));
const seconds = Math.floor((diff % (60*1000)) / 1000);
return `${days} 天 ${hours} 時 ${minutes} 分 ${seconds} 秒`;
}
// 設定生日:2025-12-25 00:00:00(本機時區)
const birthday = new Date(2025, 11, 25);
console.log('距離生日還有:', countdown(birthday));
範例 3️⃣:將 ISO 8601 字串轉成本地時間字串
function isoToLocal(isoStr) {
const d = new Date(isoStr); // 解析 ISO 字串(自動視為 UTC)
// 以本機時區格式化
return d.toLocaleString('zh-TW', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false
});
}
const iso = '2025-03-15T12:30:00Z';
console.log('本機時間顯示:', isoToLocal(iso));
範例 4️⃣:自動補零(padStart)與時間格式化函式
function formatTime(date) {
const y = date.getFullYear();
const m = String(date.getMonth() + 1).padStart(2, '0');
const d = String(date.getDate()).padStart(2, '0');
const h = String(date.getHours()).padStart(2, '0');
const min = String(date.getMinutes()).padStart(2, '0');
const s = String(date.getSeconds()).padStart(2, '0');
return `${y}-${m}-${d} ${h}:${min}:${s}`;
}
console.log('格式化時間:', formatTime(new Date()));
範例 5️⃣:利用 setHours 快速調整時區差(簡易時區轉換)
// 假設伺服器回傳的時間是 UTC,前端要顯示台北時間 (+8)
function utcToTaipei(utcDate) {
const local = new Date(utcDate);
// 加上 8 小時
local.setHours(local.getHours() + 8);
return local;
}
const utcNow = new Date(); // 假設是 UTC
const taipeiNow = utcToTaipei(utcNow);
console.log('UTC:', utcNow.toISOString());
console.log('台北時間:', taipeiNow.toLocaleString());
常見陷阱與最佳實踐
| 陷阱 | 說明 | 建議的做法 |
|---|---|---|
| 月份從 0 開始 | new Date(2025, 0, 1) 代表 1 月,易把 0 當成「沒有月份」 |
永遠記得加 +1 於顯示或輸入時 |
| 字串解析不一致 | new Date('2025-11-20') 在不同瀏覽器可能被視為本機時區或 UTC |
使用 ISO 8601 完整格式(2025-11-20T00:00:00Z)或 Date.parse 前先確認時區 |
| 毫秒溢位 | setMilliseconds(1500) 會自動進位成 1.5 秒,但不易直觀 |
使用毫秒加法:date.setTime(date.getTime() + 1500) |
| 時區差異導致日期變化 | 跨時區顯示時,toDateString() 可能因時區轉換而變成前一天 |
使用 toLocaleString 並明確指定時區(timeZone: 'Asia/Taipei') |
Date.now() vs new Date() |
Date.now() 直接回傳毫秒數,效能較佳 |
計算時間差 時優先使用 Date.now(),僅在需要完整日期物件時才 new Date() |
最佳實踐
- 統一時區:在後端與前端約定使用 UTC,顯示層再轉成本地時區。
- 避免直接比較字串:使用毫秒數 (
getTime()或Date.now()) 進行比較。 - 封裝日期工具:將常用的格式化、時區轉換、差值計算寫成模組,避免重複程式碼。
- 使用
Intl.DateTimeFormat:在需要多語系或自訂格式時,Intl提供更彈性的國際化支援。
const fmt = new Intl.DateTimeFormat('zh-TW', {
year: 'numeric',
month: 'short',
day: 'numeric',
hour: '2-digit',
minute: '2-digit',
timeZone: 'Asia/Taipei'
});
console.log('Intl 格式化:', fmt.format(new Date()));
實際應用場景
訂單系統的交易時間戳記
- 使用
Date.now()產生毫秒級唯一 ID,儲存於資料庫。 - 前端顯示時,使用
toLocaleString依使用者時區呈現。
- 使用
活動倒數計時器
- 透過
setInterval每秒更新countdown(),讓使用者即時看到剩餘時間。
- 透過
日誌(Log)檔的時間標記
- 以
new Date().toISOString()產生標準化的 UTC 時間,方便跨系統比對。
- 以
跨時區會議排程
- 先將所有會議時間轉成 UTC,存入資料庫。
- 使用者登入後,以
Intl.DateTimeFormat依所在時區顯示正確時間。
生日或周年慶提醒
- 每日跑一次批次任務,計算
diffInDays,若相差 0 天則發送推播或 Email。
- 每日跑一次批次任務,計算
總結
Date物件是 JavaScript 處理時間的核心工具,取得與設定時間的 API 大多以 本機時區 為基礎,必要時可切換到 UTC。- 透過
get*、set*方法、毫秒運算以及Intl國際化 API,我們可以精確、彈性地完成各種時間需求。 - 常見的月份起始、字串解析與時區差異問題,只要遵守 統一時區、使用完整 ISO 格式、封裝工具函式 的最佳實踐,就能大幅降低錯誤率。
掌握了「取得與設定時間」的技巧後,你將能在 訂單系統、倒數計時、跨時區排程 等實務場景中,寫出可靠且易於維護的程式碼。祝你在 JavaScript 的時間旅程中,秒秒精準、毫毫不錯!