教程
JavaScript 时间戳完整指南
本文暂提供英文版,中文翻译正在完善中。
Introduction
JavaScript provides the Date object for working with dates and timestamps. Understanding how to properly use timestamps in JavaScript is essential for web development, data processing, and time-based applications. This guide covers timestamp fundamentals, conversions, timezone handling, and best practices.
Understanding JavaScript Timestamps
Unix Timestamp in JavaScript
JavaScript uses Unix timestamps in milliseconds since January 1, 1970, 00:00:00 UTC (the Unix epoch):
JavaScript Timestamp = Milliseconds since 1970-01-01 00:00:00 UTC
Example: 1704624000000
= 1704624000 seconds since epoch
= January 8, 2024, 12:00:00 PM UTC
Important: JavaScript uses milliseconds while many other systems use seconds. Always verify units when converting.
Current Timestamp
// Current timestamp in milliseconds
const nowMs = Date.now();
console.log(nowMs); // e.g., 1704624000000
// Alternative method
const nowMs2 = new Date().getTime();
console.log(nowMs2); // Same as Date.now()
// Convert to seconds
const nowSec = Math.floor(Date.now() / 1000);
console.log(nowSec); // e.g., 1704624000
Creating Dates
Creating Date Objects
From Timestamp
// Create from milliseconds timestamp
const dateFromMs = new Date(1704624000000);
console.log(dateFromMs.toISOString()); // "2024-01-08T12:00:00.000Z"
// Create from seconds timestamp (multiply by 1000)
const dateFromSec = new Date(1704624000 * 1000);
console.log(dateFromSec.toISOString()); // "2024-01-08T12:00:00.000Z"
From Date Components
// Create from year, month, day (months are 0-indexed!)
const date1 = new Date(2024, 0, 8); // January 8, 2024
console.log(date1.toISOString()); // "2024-01-08T00:00:00.000Z"
// Create with time
const date2 = new Date(2024, 0, 8, 14, 30, 0);
console.log(date2.toISOString()); // "2024-01-08T14:30:00.000Z"
// Create from string (ISO 8601 recommended)
const date3 = new Date('2024-01-08T14:30:00.000Z');
console.log(date3.toISOString()); // "2024-01-08T14:30:00.000Z"
Common Mistake: JavaScript months are 0-indexed (0 = January, 11 = December)!
Current Date and Time
const now = new Date();
console.log(now.toISOString()); // "2024-01-08T12:34:56.789Z"
console.log(now.toString()); // "Mon Jan 08 2024 07:34:56 GMT-0500"
console.log(now.toDateString()); // "Mon Jan 08 2024"
console.log(now.toTimeString()); // "07:34:56 GMT-0500"
console.log(now.toLocaleString()); // "1/8/2024, 7:34:56 AM"
Getting Date Components
Extracting Date Parts
const date = new Date(2024, 0, 8, 14, 30, 45, 123);
// Get components
console.log(date.getFullYear()); // 2024
console.log(date.getMonth()); // 0 (January - 0-indexed!)
console.log(date.getDate()); // 8 (day of month)
console.log(date.getHours()); // 14 (hour 0-23)
console.log(date.getMinutes()); // 30 (minutes 0-59)
console.log(date.getSeconds()); // 45 (seconds 0-59)
console.log(date.getMilliseconds()); // 123 (milliseconds 0-999)
// Get day of week (0 = Sunday, 6 = Saturday)
console.log(date.getDay()); // 1 (Monday)
// Get UTC components
console.log(date.getUTCFullYear()); // 2024
console.log(date.getUTCHours()); // 19 (if local is 14:30)
Relative Time Components
const date = new Date(2024, 0, 8);
// Get timezone offset (in minutes)
const offset = date.getTimezoneOffset();
console.log(offset); // e.g., -300 (UTC-5 = -5 * 60)
// Get timestamp
const timestamp = date.getTime();
console.log(timestamp); // e.g., 1704672000000 (milliseconds)
// Get ISO 8601 string
const isoString = date.toISOString();
console.log(isoString); // "2024-01-08T00:00:00.000Z"
Setting Date Components
Modifying Dates
const date = new Date(2024, 0, 8);
// Set components (returns timestamp)
date.setFullYear(2025);
date.setMonth(11); // December
date.setDate(25);
date.setHours(18);
date.setMinutes(30);
date.setSeconds(45);
date.setMilliseconds(0);
console.log(date.toISOString()); // "2025-12-25T18:30:45.000Z"
// Set UTC components
date.setUTCFullYear(2025);
date.setUTCHours(12);
Important: Set methods return the timestamp, not the Date object. Chain carefully:
// Correct: Use same date object
const date = new Date(2024, 0, 8);
date.setDate(15);
date.setMonth(5); // June 15, 2024
// WRONG: Creates new date, loses changes
const date = new Date(2024, 0, 8);
new Date(date).setDate(15); // Original date unchanged!
Date Arithmetic
Adding and Subtracting Time
const date = new Date(2024, 0, 8);
// Add 7 days
date.setDate(date.getDate() + 7);
console.log(date.toISOString()); // "2024-01-15T00:00:00.000Z"
// Add 3 hours (3600 * 1000 ms)
date.setTime(date.getTime() + (3 * 3600 * 1000));
console.log(date.toISOString()); // "2024-01-15T03:00:00.000Z"
// Subtract 1 month
date.setMonth(date.getMonth() - 1);
console.log(date.toISOString()); // "2023-12-15T03:00:00.000Z"
// Add 1 year
date.setFullYear(date.getFullYear() + 1);
console.log(date.toISOString()); // "2024-12-15T03:00:00.000Z"
Best Practice: Use timestamp arithmetic for precision:
> // Add 1 hour in milliseconds (60 * 60 * 1000)
> const oneHour = 60 * 60 * 1000;
> const newDate = new Date(date.getTime() + oneHour);
>
Time Differences
const date1 = new Date(2024, 0, 8);
const date2 = new Date(2024, 0, 15);
// Difference in milliseconds
const diffMs = date2 - date1;
console.log(diffMs); // 604800000 (7 days in ms)
// Convert to seconds, minutes, hours, days
const diffSec = Math.floor(diffMs / 1000);
const diffMin = Math.floor(diffMs / (1000 * 60));
const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
console.log(`${diffDays} days`); // "7 days"
console.log(`${diffHours} hours`); // "168 hours"
Formatting Dates
Built-in Formatting
toLocaleString Family
const date = new Date(2024, 0, 8, 14, 30, 45);
// Locale-specific formats
console.log(date.toLocaleDateString()); // "1/8/2024"
console.log(date.toLocaleTimeString()); // "2:30:45 PM"
console.log(date.toLocaleString()); // "1/8/2024, 2:30:45 PM"
// With locale options
console.log(date.toLocaleDateString('en-US', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric'
}));
// "Monday, January 8, 2024"
console.log(date.toLocaleDateString('zh-CN', {
year: 'numeric',
month: 'long',
day: 'numeric'
}));
// "2024年1月8日"
International Formats
const date = new Date(2024, 0, 8);
// ISO 8601 (always UTC)
console.log(date.toISOString()); // "2024-01-08T00:00:00.000Z"
// UTC string
console.log(date.toUTCString()); // "Sun, 07 Jan 2024 00:00:00 GMT"
// Date string (local time)
console.log(date.toString()); // "Mon Jan 08 2024 00:00:00 GMT-0500"
Best Practice: Always use
toISOString()for API calls and database storage to avoid timezone issues.
Custom Formatting
// Manual formatting (use Intl.DateTimeFormat for i18n)
function formatDate(date) {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
console.log(formatDate(new Date(2024, 0, 8, 14, 30, 45)));
// "2024-01-08 14:30:45"
Recommendation: Use libraries like date-fns, luxon, or day.js for complex formatting instead of manual formatting.
Timezone Handling
Working with Timezones
Getting Timezone Info
const date = new Date();
// Get timezone offset (in minutes)
const offset = date.getTimezoneOffset();
console.log(offset); // e.g., -300 (UTC-5) or 300 (UTC+5)
// Convert offset to hours
const offsetHours = offset / 60;
console.log(offsetHours); // -5 or 5
// Get timezone name (browser-specific)
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
console.log(timezone); // e.g., "America/New_York"
Converting Between Timezones
const date = new Date(2024, 0, 8, 14, 30, 0);
// Convert to different timezone using toLocaleString
const nyTime = date.toLocaleString('en-US', {
timeZone: 'America/New_York',
timeZoneName: 'short'
});
console.log(nyTime); // "1/8/2024, 9:30:00 AM EST"
const tokyoTime = date.toLocaleString('en-US', {
timeZone: 'Asia/Tokyo'
});
console.log(tokyoTime); // "1/8/2024, 11:30:00 PM"
// Extract time components in specific timezone
const tokyoDate = new Date(date.toLocaleString('en-US', {
timeZone: 'Asia/Tokyo'
}));
console.log(tokyoDate.getHours()); // 23 (11 PM)
Best Practice: Always work with UTC internally and convert to local timezone only for display.
UTC vs Local Time
const date = new Date(2024, 0, 8, 14, 30, 0);
// Local time methods
console.log(date.getHours()); // Local hour (e.g., 14 for EST)
console.log(date.getTime()); // Timestamp (same regardless of timezone)
// UTC methods
console.log(date.getUTCHours()); // UTC hour (e.g., 19 for EST)
console.log(date.getUTCDate()); // UTC day of month
Parsing Dates
Parsing Date Strings
Using Date Constructor
// ISO 8601 (recommended)
const isoDate = new Date('2024-01-08T14:30:00.000Z');
console.log(isoDate.toISOString()); // "2024-01-08T14:30:00.000Z"
// Short date format (browser-dependent, avoid!)
const shortDate = new Date('01/08/2024');
console.log(shortDate); // May be Jan 8 or Aug 8 depending on locale
// RFC 2822 format
const rfcDate = new Date('Mon, 08 Jan 2024 14:30:00 GMT');
console.log(rfcDate.toISOString()); // "2024-01-08T14:30:00.000Z"
Problem: Date parsing is inconsistent across browsers and locales.
Manual Parsing
// Parse ISO 8601 string manually
function parseISOString(isoString) {
const date = new Date(isoString);
if (isNaN(date.getTime())) {
throw new Error('Invalid date string');
}
return date;
}
// Parse custom format (YYYY-MM-DD)
function parseCustomDate(dateString) {
const [year, month, day] = dateString.split('-').map(Number);
return new Date(year, month - 1, day); // months are 0-indexed
}
console.log(parseCustomDate('2024-01-08').toISOString());
// "2024-01-08T00:00:00.000Z"
Recommendation: Use libraries like date-fns/parse or luxon/DateTime.fromISO for reliable parsing.
Validating Dates
// Check if date is valid
function isValidDate(date) {
return date instanceof Date && !isNaN(date.getTime());
}
// Examples
const validDate = new Date(2024, 0, 8);
const invalidDate = new Date('invalid');
console.log(isValidDate(validDate)); // true
console.log(isValidDate(invalidDate)); // false
console.log(isNaN(invalidDate.getTime())); // true (NaN)
Common Pitfalls
Month Indexing
// Common mistake: Using 1-12 for months
const date = new Date(2024, 12, 8); // January 2025!
console.log(date.toISOString()); // "2025-01-08T00:00:00.000Z"
// Correct: Use 0-11 for months
const date = new Date(2024, 11, 8); // December 2024
console.log(date.toISOString()); // "2024-12-08T00:00:00.000Z"
Timezone Confusion
const date = new Date(2024, 0, 8, 0, 0, 0);
// These produce different values!
console.log(date.getTime()); // 1704672000000 (same)
console.log(date.toString()); // "Mon Jan 08 2024 00:00:00 GMT-0500"
console.log(date.toISOString()); // "2024-01-08T05:00:00.000Z"
// Midnight EST = 5:00 AM UTC
Problem: Creating dates without timezone info assumes local time.
String Parsing Inconsistencies
// Different browsers may parse differently
const date1 = new Date('2024-01-08'); // Might be Jan 8 or Jan 1
const date2 = new Date('2024/01/08'); // Might be parsed differently
const date3 = new Date('01-08-2024'); // Very ambiguous!
// Always use ISO 8601
const date = new Date('2024-01-08T00:00:00Z');
console.log(date.toISOString()); // Consistent across all browsers
Math Overflow
const date = new Date(2024, 0, 31);
// Add 2 months to Jan 31
date.setMonth(date.getMonth() + 2);
console.log(date.toISOString()); // "2024-03-31T00:00:00.000Z" ✓
// Add 1 month to Jan 31 (February doesn't have 31!)
date.setMonth(date.getMonth() + 1);
console.log(date.toISOString()); // "2024-03-02T00:00:00.000Z" ✓
// JavaScript auto-adjusts overflow
Benefit: JavaScript automatically handles date overflow (Feb 31 → Mar 2 or 3 depending on leap year).
Best Practices
Performance
Avoid Frequent Date Creation
// BAD: Create new Date in loop
for (let i = 0; i < 1000; i++) {
const now = new Date();
// ... operations
}
// GOOD: Create once, reuse
const now = new Date();
const timestamp = now.getTime();
for (let i = 0; i < 1000; i++) {
// ... operations with timestamp
}
Use Timestamp for Comparisons
const date1 = new Date(2024, 0, 8);
const date2 = new Date(2024, 0, 15);
// BAD: Compare Date objects (slow)
if (date1 < date2) { }
// GOOD: Compare timestamps (fast)
if (date1.getTime() < date2.getTime()) { }
// Even better: Use timestamps directly
const ts1 = date1.getTime();
const ts2 = date2.getTime();
if (ts1 < ts2) { }
Cache Timezone Offset
// Cache timezone offset (doesn't change during runtime)
const TZ_OFFSET = new Date().getTimezoneOffset() * 60 * 1000;
// Use in conversions
function toLocalTime(timestamp) {
return new Date(timestamp + TZ_OFFSET);
}
console.log(toLocalTime(Date.now()));
Data Integrity
// Validate before operations
function safeDateOperation(callback) {
try {
const result = callback();
if (isNaN(result.getTime())) {
throw new Error('Invalid date result');
}
return result;
} catch (error) {
console.error('Date operation failed:', error);
return new Date(); // Return current time as fallback
}
}
// Usage
const result = safeDateOperation(() => {
return new Date(invalidInput);
});
Storage Best Practices
// Store as ISO 8601 string
function serializeDate(date) {
return date.toISOString();
}
// Deserialize from ISO 8601
function deserializeDate(isoString) {
return new Date(isoString);
}
// Usage in JSON
const data = {
timestamp: Date.now(),
isoDate: new Date().toISOString(),
userCreated: serializeDate(new Date())
};
// Parse from API
const createdDate = deserializeDate(apiResponse.userCreated);
Common Operations
Utility Functions
Start/End of Day
function startOfDay(date) {
const d = new Date(date);
d.setHours(0, 0, 0, 0);
return d;
}
function endOfDay(date) {
const d = new Date(date);
d.setHours(23, 59, 59, 999);
return d;
}
console.log(startOfDay(new Date()).toISOString());
// "2024-01-08T00:00:00.000Z"
Start/End of Week
function startOfWeek(date) {
const d = new Date(date);
const day = d.getDay();
const diff = d.getDate() - day + (day === 0 ? -6 : 1);
d.setDate(diff);
return startOfDay(d);
}
function endOfWeek(date) {
const d = startOfWeek(new Date(date));
d.setDate(d.getDate() + 6);
return endOfDay(d);
}
console.log(startOfWeek(new Date(2024, 0, 8)).toISOString());
// "2024-01-01T00:00:00.000Z" (Monday)
Start/End of Month
function startOfMonth(date) {
return new Date(date.getFullYear(), date.getMonth(), 1);
}
function endOfMonth(date) {
return new Date(date.getFullYear(), date.getMonth() + 1, 0);
}
console.log(startOfMonth(new Date(2024, 0, 15)).toISOString());
// "2024-01-01T00:00:00.000Z"
console.log(endOfMonth(new Date(2024, 0, 15)).toISOString());
// "2024-01-31T00:00:00.000Z"
Age Calculation
function calculateAge(birthDate) {
const today = new Date();
const birth = new Date(birthDate);
let years = today.getFullYear() - birth.getFullYear();
const monthDiff = today.getMonth() - birth.getMonth();
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birth.getDate())) {
years--;
}
return years;
}
console.log(calculateAge('1990-06-15'));
// 33 (assuming current date is 2024-01-08)
Business Days Calculation
function addBusinessDays(startDate, days) {
const result = new Date(startDate);
let addedDays = 0;
while (addedDays < days) {
result.setDate(result.getDate() + 1);
const dayOfWeek = result.getDay();
if (dayOfWeek !== 0 && dayOfWeek !== 6) { // Not weekend
addedDays++;
}
}
return result;
}
console.log(addBusinessDays(new Date(2024, 0, 8), 5).toISOString());
// "2024-01-15T00:00:00.000Z" (skips weekend)
Examples and Use Cases
Countdown Timer
function countdown(targetDate) {
const now = Date.now();
const target = new Date(targetDate).getTime();
const diff = target - now;
if (diff <= 0) {
return { expired: true };
}
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
const seconds = Math.floor((diff % (1000 * 60)) / 1000);
return {
expired: false,
days,
hours,
minutes,
seconds,
totalMs: diff
};
}
console.log(countdown('2024-12-31'));
// { expired: false, days: 357, hours: 11, minutes: 29, seconds: 12, totalMs: ... }
Relative Time (e.g., "2 hours ago")
function timeAgo(timestamp) {
const now = Date.now();
const diff = now - timestamp;
const seconds = Math.floor(diff / 1000);
if (seconds < 60) return 'just now';
const minutes = Math.floor(seconds / 60);
if (minutes < 60) return `${minutes} minute${minutes !== 1 ? 's' : ''} ago`;
const hours = Math.floor(minutes / 60);
if (hours < 24) return `${hours} hour${hours !== 1 ? 's' : ''} ago`;
const days = Math.floor(hours / 24);
if (days < 30) return `${days} day${days !== 1 ? 's' : ''} ago`;
const months = Math.floor(days / 30);
if (months < 12) return `${months} month${months !== 1 ? 's' : ''} ago`;
const years = Math.floor(days / 365);
return `${years} year${years !== 1 ? 's' : ''} ago`;
}
const oneHourAgo = Date.now() - (60 * 60 * 1000);
console.log(timeAgo(oneHourAgo)); // "1 hour ago"
Date Range Validation
function isDateInRange(date, startDate, endDate) {
const timestamp = date.getTime();
return timestamp >= startDate.getTime() && timestamp <= endDate.getTime();
}
// Example: Check if date is in Q1 2024
const q1Start = new Date(2024, 0, 1);
const q1End = new Date(2024, 2, 31);
const testDate = new Date(2024, 1, 15);
console.log(isDateInRange(testDate, q1Start, q1End)); // true
console.log(isDateInRange(new Date(2024, 3, 1), q1Start, q1End)); // false
Best Practices Summary
JavaScript Date Checklist
✅ Always use ISO 8601 format ('2024-01-08T14:30:00.000Z') for strings
✅ Work with timestamps internally, convert to Date only for display
✅ Use toISOString() for API calls and database storage
✅ Remember months are 0-indexed (0 = January, 11 = December)
✅ Cache timezone offset and Date.now() to avoid repeated calls
✅ Validate dates with isNaN(date.getTime())
✅ Use Intl.DateTimeFormat for i18n-aware formatting
✅ Consider libraries (date-fns, luxon, day.js) for complex operations
✅ Use timestamp arithmetic for precision (add/subtract milliseconds)
✅ Handle date overflow gracefully (JavaScript auto-adjusts)
❌ Don't use locale-specific strings for parsing (inconsistent across browsers)
❌ Don't mix UTC and local methods in same calculation
❌ Don't create Date objects in loops (reuse or use timestamps)
❌ Don't assume browser timezones (always validate with getTimezoneOffset)
❌ Don't rely on automatic string parsing (use ISO 8601)
❌ Don't forget about DST transitions when calculating business days
Performance Tips
✅ Cache Date.now() instead of calling repeatedly
✅ Use timestamps for comparisons (faster than Date objects)
✅ Minimize Date object creation in loops
✅ Use Math.floor() instead of bitwise operators for readability
✅ Store timezone offset as constant for repeated calculations
❌ Don't use Date.parse() on non-ISO strings (unreliable)
❌ Don't create Date objects in hot code paths
❌ Don't use toLocaleString() in performance-critical sections
Related Tools
- Unix Timestamp Converter - Convert Unix timestamps to dates
- Current Timestamp - Get current timestamp in multiple formats
- Timestamp Format Converter - Convert between timestamp formats
- JavaScript Timestamp Helper - JavaScript-specific examples
- UTC/Local Converter - Convert between UTC and local time
Additional Resources
For production applications with complex date/time requirements, consider using libraries like:
- date-fns: Modular, immutable date utilities
- luxon: Modern API with timezone support (from Moment.js creators)
- day.js: Lightweight alternative to Moment.js (2KB)
- temporal-polyfill: Future TC39 Temporal API proposal
Native Date is sufficient for basic operations, but libraries provide better ergonomics and timezone handling for complex use cases.
本次补充
不要把显示格式与时间点混为一谈:toISOString() 始终输出 UTC,而 toLocaleString() 仅改变显示。比较或存储时使用毫秒数,展示时再做本地化。
动手试试
测试时间戳转换
需要更多选项? JavaScript 时间戳助手