本文 AI 產出,尚未審核

JavaScript 日期與時間格式化(toLocaleString 等)

簡介

在前端開發中,日期與時間是最常見的資料類型之一。無論是顯示文章發佈時間、計算倒數計時,或是與後端 API 交換時間戳,正確且易讀的日期格式都是使用者體驗的關鍵。
傳統上,我們會使用 Date 物件的 getFullYear()getMonth() 等方法自行拼接字串,但這種做法不僅繁瑣,還容易忽略 時區本地化(locale)等細節。

ECMAScript 內建的 toLocaleStringtoLocaleDateStringtoLocaleTimeString 等方法,讓我們可以一次完成本地化、時區與格式的設定,省去大量手動處理的工作。本篇文章將深入探討這些方法的用法,並提供實務範例、常見陷阱與最佳實踐,幫助你在 JavaScript 中自信地處理日期格式化。


核心概念

1. Date 物件的基本操作

在深入本地化之前,先了解 Date 物件的建立與基本屬性:

// 建立目前時間的 Date 物件
const now = new Date();

// 取得各個時間單位(回傳的是數值)
console.log(now.getFullYear());   // 2025
console.log(now.getMonth());      // 0~11,0 代表 1 月
console.log(now.getDate());       // 1~31
console.log(now.getHours());      // 0~23
console.log(now.getMinutes());    // 0~59
console.log(now.getSeconds());    // 0~59

注意:月份是從 0 開始計算,若要顯示「1 月」需要自行加 1。

2. 為什麼要使用 toLocaleString 系列?

toLocaleStringtoLocaleDateStringtoLocaleTimeString 皆接受兩個參數:

dateObj.toLocaleString([locales], [options])
參數 說明
locales 字串或字串陣列,指定要使用的語系(例:'zh-TW''en-US')。若省略,會使用執行環境的預設語系。
options 物件,設定想要顯示的欄位與格式(如 year: 'numeric'hour12: false)。

使用這兩個參數,我們可以一次決定 語系、本地化文字、時間格式、時區,而不必自行拼接或使用第三方函式庫。

3. 常見的 options 屬性

屬性 可能的值 說明
year 'numeric''2-digit' 顯示完整年份或兩位數年份
month 'numeric''2-digit''short''long' 數字、兩位數、縮寫或全名
day 'numeric''2-digit' 日期
weekday 'short''long' 星期幾
hour 'numeric''2-digit' 小時
minute 'numeric''2-digit' 分鐘
second 'numeric''2-digit'
hour12 truefalse 12 小時制或 24 小時制
timeZone 時區字串(例:'Asia/Taipei' 指定顯示的時區
timeZoneName 'short''long' 顯示時區縮寫或全名

4. 範例一:基本的本地化日期字串

const date = new Date('2025-03-15T14:30:00');

// 台灣(zh-TW)顯示完整日期與時間(24 小時制)
const twFull = date.toLocaleString('zh-TW', {
  year: 'numeric',
  month: 'long',
  day: 'numeric',
  hour: '2-digit',
  minute: '2-digit',
  second: '2-digit',
  hour12: false,
  timeZone: 'Asia/Taipei',
});
console.log(twFull); // => 2025年3月15日 14:30:00

說明month: 'long' 會輸出「3月」的全名,hour12: false 強制使用 24 小時制,timeZone 確保即使伺服器在不同時區,仍以台北時間顯示。

5. 範例二:僅顯示日期(不含時間)並加上星期

const today = new Date();

const options = {
  weekday: 'short',   // Wed、Thu…
  year: 'numeric',
  month: 'short',     // Mar、Apr…
  day: 'numeric',
};

console.log(today.toLocaleDateString('en-US', options));
// 例:Thu, Mar 12, 2025

說明weekday: 'short' 會顯示縮寫的星期,month: 'short' 產生英文縮寫月份。若改成 'zh-TW',結果會是「星期四 3月 12日 2025」。

6. 範例三:自訂時間格式(12 小時制 + AM/PM)

const time = new Date('2025-03-15T09:05:07');

const formatted = time.toLocaleTimeString('en-US', {
  hour: 'numeric',
  minute: '2-digit',
  second: '2-digit',
  hour12: true,           // 12 小時制
  timeZone: 'America/New_York',
  timeZoneName: 'short',  // 顯示縮寫時區 (EDT)
});

console.log(formatted); // => 5:05:07 AM EDT

說明hour12: true 會自動加上 AM/PM,timeZoneName: 'short' 把時區縮寫加入字串,方便使用者了解時間來源。

7. 範例四:多語系切換(國際化)

const eventDate = new Date('2025-12-31T23:59:59');

// 依不同語系產生不同格式
const locales = ['zh-TW', 'en-US', 'ja-JP'];
locales.forEach(loc => {
  const str = eventDate.toLocaleString(loc, {
    year: 'numeric',
    month: 'long',
    day: 'numeric',
    hour: 'numeric',
    minute: 'numeric',
    hour12: loc === 'en-US', // 只在美式英語使用 12 小時制
    timeZone: 'Asia/Taipei',
  });
  console.log(`${loc}: ${str}`);
});

/* 輸出範例
zh-TW: 2025年12月31日 23:59
en-US: December 31, 2025, 11:59 PM
ja-JP: 2025年12月31日 23:59
*/

說明:透過迴圈一次產出多語系的日期字串,適合在多國語系網站上動態切換。

8. 範例五:以 Intl.DateTimeFormat 建立可重複使用的 formatter

如果在大量資料(例如列表或表格)中頻繁格式化日期,直接呼叫 toLocaleString 會產生不必要的物件建立成本。可以先建立 Intl.DateTimeFormat 實例,再重複使用:

// 建立一次 formatter
const formatter = new Intl.DateTimeFormat('zh-TW', {
  year: 'numeric',
  month: '2-digit',
  day: '2-digit',
  hour: '2-digit',
  minute: '2-digit',
  hour12: false,
  timeZone: 'Asia/Taipei',
});

// 在迴圈中使用
const timestamps = [
  1735680000000, // 2025-01-01 00:00:00 UTC
  1735766400000, // 2025-01-02 00:00:00 UTC
  // ...
];

timestamps.forEach(ts => {
  console.log(formatter.format(new Date(ts)));
});
// 2025/01/01 08:00
// 2025/01/02 08:00

說明formatter.format 只接受 Date 或時間戳,效能比每次呼叫 toLocaleString 好。


常見陷阱與最佳實踐

陷阱 說明 解決方案
時區不一致 Date 物件在建立時會根據本機時區解讀字串,若直接使用 new Date('2025-03-15'),會被視為 UTC+0 的午夜,導致跨時區時差。 使用 ISO 8601 完整字串(包含時區)或在 toLocaleString 指定 timeZone
月份從 0 開始 手動拼接日期時忘記加 1,導致顯示錯誤的月份。 盡量使用本地化方法,或在自行處理時 month + 1
瀏覽器支援差異 部分舊版瀏覽器(IE)不支援 toLocaleStringoptions 參數,會回傳不符合預期的字串。 在需要兼容的情況下使用 polyfill(如 core-js)或第三方函式庫(date-fnsdayjs)。
hour12 與語系衝突 某些語系(如 zh-TW)預設是 24 小時制,若強制 hour12: true 可能產生不自然的顯示。 根據使用者語系自行決定 hour12,或提供 UI 切換選項。
timeZoneName 產生的字串長度 在 UI 空間有限的情況下,timeZoneName: 'long' 會產生「Coordinated Universal Time」之類的長字串。 使用 'short' 或自行省略時區顯示。

最佳實踐

  1. 統一時區:在前端與後端溝通時,約定使用 UTC 或特定時區(如 Asia/Taipei),避免因本機時區差異產生錯誤。
  2. 使用 Intl.DateTimeFormat:大量渲染時,先建立 formatter 再重複使用,可提升效能。
  3. 根據使用者語系自動切換navigator.language 可取得瀏覽器語系,配合 toLocaleString 自動產生符合當地慣例的格式。
  4. 避免手動拼接:盡量使用內建的本地化方法,減少錯誤與維護成本。
  5. 測試跨時區:在開發階段使用不同時區的模擬器(Chrome DevTools → Sensors)驗證顯示是否正確。

實際應用場景

1. 文章發佈時間顯示

在部落格或新聞網站,常見需求是「2025 年 3 月 15 日 14:30」的顯示。使用 toLocaleString 可一次完成:

function formatPostDate(timestamp) {
  return new Date(timestamp).toLocaleString('zh-TW', {
    year: 'numeric',
    month: 'long',
    day: 'numeric',
    hour: '2-digit',
    minute: '2-digit',
    hour12: false,
    timeZone: 'Asia/Taipei',
  });
}

2. 跨國電商的訂單時間

電商平台需要同時呈現 使用者本地時間系統(UTC)時間

const orderTimeUTC = '2025-04-01T08:15:00Z';
const userLocale = navigator.language || 'en-US';

const local = new Date(orderTimeUTC).toLocaleString(userLocale, {
  year: 'numeric',
  month: 'short',
  day: 'numeric',
  hour: 'numeric',
  minute: 'numeric',
  hour12: false,
  timeZoneName: 'short',
});

const utc = new Date(orderTimeUTC).toISOString().replace('T', ' ').substring(0, 16) + ' UTC';

console.log(`訂單時間(本地):${local}`);
console.log(`訂單時間(UTC):${utc}`);

3. 行事曆或排程系統的時區切換

允許使用者自行選擇時區(例如會議跨時區):

function formatForTimezone(date, tz) {
  return date.toLocaleString('zh-TW', {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
    hour12: false,
    timeZone: tz,
    timeZoneName: 'short',
  });
}

// 範例:顯示同一時間在台北、紐約、倫敦的差異
const meeting = new Date('2025-06-10T15:00:00Z');
console.log('台北:', formatForTimezone(meeting, 'Asia/Taipei'));
console.log('紐約:', formatForTimezone(meeting, 'America/New_York'));
console.log('倫敦:', formatForTimezone(meeting, 'Europe/London'));

4. 報表匯出(CSV/Excel)中的日期字串

匯出時常需要把日期轉成 ISO 8601固定格式,避免使用者在 Excel 中自動轉換:

function toCSVDate(date) {
  // 2025-03-15 14:30:00
  return date.toLocaleString('sv-SE', {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit',
    hour12: false,
    timeZone: 'Asia/Taipei',
  }).replace(' ', 'T');
}

總結

  • 日期與時間的本地化 不只是字串的翻譯,更涉及時區、12/24 小時制、星期與月份名稱等多層面的調整。
  • JavaScript 內建的 toLocaleStringtoLocaleDateStringtoLocaleTimeString 搭配 Intl.DateTimeFormat,提供了 一致、可讀且效能友善 的解決方案。
  • 在實務開發中,統一時區、使用 formatter、根據使用者語系自動切換 是避免錯誤與提升使用者體驗的關鍵。
  • 透過本文的範例,你可以快速在部落格、電商、行事曆與報表等常見情境中,正確且優雅地呈現日期與時間。

掌握這些技巧後,你將能在任何前端專案裡,輕鬆處理日期格式化的挑戰,讓使用者感受到更貼近生活的時間資訊。祝開發順利! 🚀