浏览器时间API:Date、Intl.DateTimeFormat等

The Date Object: Old but Still Central

JavaScript's Date object has been part of the language since 1995. Despite its quirks, it remains the foundation for time in the browser. It stores time internally as milliseconds since the Unix epoch (UTC), but most methods return local time:

// Creating dates
const now = new Date();                          // current time
const fromISO = new Date("2024-03-01T14:00:00Z"); // parse ISO 8601
const fromMs = new Date(1700000000000);            // from milliseconds

// Getting UTC values (consistent everywhere)
now.getUTCFullYear()     // 2024
now.getUTCMonth()        // 0-11 (!)
now.getUTCDate()         // day of month
now.getUTCHours()
now.toISOString()        // "2024-03-01T14:00:00.000Z"

// Getting local values (varies by browser timezone)
now.getFullYear()
now.getHours()
now.toLocaleDateString("ko-KR")  // "2024. 3. 1."

Intl.DateTimeFormat: Locale-Aware Formatting

The Intl.DateTimeFormat API provides powerful, locale-aware date formatting without external libraries:

const d = new Date("2024-03-01T14:00:00Z");

// Korean formatting in Seoul timezone
new Intl.DateTimeFormat("ko-KR", {
  timeZone: "Asia/Seoul",
  year: "numeric", month: "long", day: "numeric",
  hour: "2-digit", minute: "2-digit",
  hour12: false,
}).format(d);
// "2024년 3월 1일 23:00"

// Relative time display
new Intl.RelativeTimeFormat("ko", { numeric: "auto" })
  .format(-2, "day");   // "그저께"
  .format(-1, "day");   // "어제"
  .format(0, "day");    // "오늘"
  .format(3, "hour");   // "3시간 후"

Performance.now(): High-Resolution Timing

For measuring elapsed time precisely (e.g., benchmarking), use performance.now() instead of Date.now(). It returns milliseconds since page load with sub-millisecond precision and is not subject to system clock adjustments:

const start = performance.now();
// ... code to measure ...
const elapsed = performance.now() - start;
console.log(`${elapsed.toFixed(3)}ms`);

Intl.DateTimeFormat.formatToParts()

For custom date display, formatToParts() returns each part of a formatted date as a separate token:

const parts = new Intl.DateTimeFormat("en-US", {
  timeZone: "America/New_York",
  month: "short", day: "numeric", year: "numeric",
}).formatToParts(new Date("2024-03-01T14:00:00Z"));
// [{type:"month", value:"Mar"}, {type:"literal", value:" "},
//  {type:"day", value:"1"}, {type:"literal", value:", "},
//  {type:"year", value:"2024"}]

Browser Timezone Detection

// Get the user's IANA timezone name
Intl.DateTimeFormat().resolvedOptions().timeZone
// "Asia/Seoul", "America/New_York", etc.

// Get UTC offset in minutes
new Date().getTimezoneOffset()  // -540 for KST (note: negative means ahead of UTC)

The Temporal API (Coming Soon)

The Temporal API (TC39 Stage 3) will fix all of Date's problems. A polyfill is available today:

import { Temporal } from "@js-temporal/polyfill";

const now = Temporal.Now.zonedDateTimeISO("Asia/Seoul");
const yesterday = now.subtract({ days: 1 });
console.log(now.toString());  // 2024-03-01T23:00:00+09:00[Asia/Seoul]