Tutorial

JavaScript时间戳转换完全教程:详细示例和最佳实践

简介

在JavaScript中转换时间戳是Web开发人员的基本技能。无论您是在处理API、数据库还是用户界面,您都会经常需要在Unix时间戳和人类可读日期之间进行转换。本教程将指导您了解需要知道的一切。

您将学到什么

  • ✅ 获取当前时间戳
  • ✅ 将时间戳转换为Date对象
  • ✅ 将Date对象转换为时间戳
  • ✅ 格式化时间戳以供显示
  • ✅ 处理不同的时间戳精度
  • ✅ 处理时区
  • ✅ 常见陷阱及避免方法

前提条件

只需要基本的JavaScript知识。本教程不需要外部库(虽然我们会在最后提到一些流行的库)。

步骤1:获取当前时间戳

最简单的操作 - 将当前时间作为时间戳获取。

方法1:Date.now()(推荐)

// 获取毫秒级当前时间戳
const timestamp = Date.now();
console.log(timestamp);
// 输出:1704067200000(13位)

为什么使用这个?

  • ✅ 最快的方法
  • ✅ 无需创建Date对象
  • ✅ 最常用

方法2:new Date().getTime()

// 创建Date对象并获取时间戳
const timestamp = new Date().getTime();
console.log(timestamp);
// 输出:1704067200000(13位)

何时使用?

  • 当您已经有Date对象时
  • 当您需要链式调用方法时

方法3:一元加号运算符

// 使用一元加号的简写
const timestamp = +new Date();
console.log(timestamp);
// 输出:1704067200000(13位)

何时使用?

  • 代码高尔夫或简洁性很重要时
  • 不推荐初学者使用(可读性较差)

获取秒级时间戳

JavaScript默认使用毫秒,但许多API使用秒:

// 获取秒级时间戳(10位)
const timestampInSeconds = Math.floor(Date.now() / 1000);
console.log(timestampInSeconds);
// 输出:1704067200(10位)

// 替代方法:使用parseInt
const timestampSec = parseInt(Date.now() / 1000);
console.log(timestampSec);
// 输出:1704067200

步骤2:将时间戳转换为Date对象

将Unix时间戳转换为JavaScript Date对象。

基本转换

// 毫秒时间戳(13位)
const timestamp = 1704067200000;
const date = new Date(timestamp);

console.log(date);
// 输出:Mon Jan 01 2024 00:00:00 GMT+0000 (UTC)

console.log(date.toISOString());
// 输出:2024-01-01T00:00:00.000Z

转换秒级时间戳

许多API返回秒级时间戳(10位),而不是毫秒:

// 秒级时间戳(10位)- 必须乘以1000!
const timestampInSeconds = 1704067200;
const date = new Date(timestampInSeconds * 1000);

console.log(date.toISOString());
// 输出:2024-01-01T00:00:00.000Z

⚠️ 常见错误:

// ❌ 错误:直接使用秒级时间戳
const wrongDate = new Date(1704067200);
console.log(wrongDate.toISOString());
// 输出:1970-01-20T17:27:47.200Z(错误!)

// ✅ 正确:乘以1000
const correctDate = new Date(1704067200 * 1000);
console.log(correctDate.toISOString());
// 输出:2024-01-01T00:00:00.000Z(正确!)

检测时间戳精度

自动检测时间戳是秒还是毫秒的辅助函数:

function createDateFromTimestamp(timestamp) {
    // 如果时间戳有10位,则为秒
    // 如果时间戳有13位,则为毫秒
    const digitCount = timestamp.toString().length;

    if (digitCount === 10) {
        // 秒 - 乘以1000
        return new Date(timestamp * 1000);
    } else if (digitCount === 13) {
        // 毫秒 - 直接使用
        return new Date(timestamp);
    } else {
        throw new Error(`无效的时间戳:${timestamp}`);
    }
}

// 使用方法
const date1 = createDateFromTimestamp(1704067200);     // 10位(秒)
const date2 = createDateFromTimestamp(1704067200000);  // 13位(毫秒)

console.log(date1.toISOString());  // 2024-01-01T00:00:00.000Z
console.log(date2.toISOString());  // 2024-01-01T00:00:00.000Z

步骤3:将Date对象转换为时间戳

将JavaScript Date对象转换回Unix时间戳。

从当前日期

const now = new Date();

// 获取毫秒时间戳
const timestampMs = now.getTime();
console.log(timestampMs);  // 1704067200000

// 获取秒级时间戳
const timestampSec = Math.floor(now.getTime() / 1000);
console.log(timestampSec);  // 1704067200

从特定日期字符串

// ISO 8601格式(推荐)
const date1 = new Date('2024-01-01T00:00:00Z');
console.log(date1.getTime());  // 1704067200000

// 不同的日期格式
const date2 = new Date('January 1, 2024');
const date3 = new Date('01/01/2024');
const date4 = new Date('2024-01-01');

console.log(date2.getTime());  // 取决于本地时区
console.log(date3.getTime());  // 取决于本地时区
console.log(date4.getTime());  // 通常为本地时区的00:00:00

⚠️ 重要: 不同的日期字符串格式在时区方面表现不同!

从日期组件

// 从年、月、日等创建日期
// 注意:月份从0开始索引(0 = 一月,11 = 十二月)
const date = new Date(2024, 0, 1, 0, 0, 0);  // 2024年1月1日 00:00:00
const timestamp = date.getTime();

console.log(timestamp);  // 本地时区时间戳

// 对于UTC,使用Date.UTC()
const utcTimestamp = Date.UTC(2024, 0, 1, 0, 0, 0);
console.log(utcTimestamp);  // 1704067200000(UTC)

步骤4:格式化时间戳

将时间戳转换为人类可读格式。

JavaScript内置方法

const date = new Date(1704067200000);

// ISO 8601格式(最适合API)
console.log(date.toISOString());
// 输出:"2024-01-01T00:00:00.000Z"

// 特定区域设置的日期字符串
console.log(date.toLocaleDateString());
// 输出:"1/1/2024"(美国)或"01/01/2024"(英国)

// 特定区域设置的日期和时间
console.log(date.toLocaleString());
// 输出:"1/1/2024, 12:00:00 AM"

// 特定区域设置的时间
console.log(date.toLocaleTimeString());
// 输出:"12:00:00 AM"

// 完整日期字符串
console.log(date.toDateString());
// 输出:"Mon Jan 01 2024"

// UTC字符串
console.log(date.toUTCString());
// 输出:"Mon, 01 Jan 2024 00:00:00 GMT"

自定义格式化

function formatTimestamp(timestamp, format = 'full') {
    const date = new Date(timestamp);

    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');

    const formats = {
        'full': `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`,
        'date': `${year}-${month}-${day}`,
        'time': `${hours}:${minutes}:${seconds}`,
        'short': `${month}/${day}/${year}`,
        'iso': date.toISOString()
    };

    return formats[format] || formats.full;
}

// 使用方法
const timestamp = 1704067200000;
console.log(formatTimestamp(timestamp, 'full'));   // "2024-01-01 00:00:00"
console.log(formatTimestamp(timestamp, 'date'));   // "2024-01-01"
console.log(formatTimestamp(timestamp, 'time'));   // "00:00:00"
console.log(formatTimestamp(timestamp, 'short'));  // "01/01/2024"

使用Intl.DateTimeFormat(现代方法)

const timestamp = 1704067200000;
const date = new Date(timestamp);

// 美式英语格式
const usFormatter = new Intl.DateTimeFormat('zh-CN', {
    year: 'numeric',
    month: 'long',
    day: 'numeric',
    hour: '2-digit',
    minute: '2-digit'
});
console.log(usFormatter.format(date));
// 输出:"2024年1月1日 00:00"

// 自定义格式
const customFormatter = new Intl.DateTimeFormat('zh-CN', {
    weekday: 'long',
    year: 'numeric',
    month: 'short',
    day: 'numeric',
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit',
    timeZoneName: 'short'
});
console.log(customFormatter.format(date));
// 输出:"2024年1月1日星期一 00:00:00 UTC"

步骤5:处理时区

处理不同的时区对于准确的时间戳转换至关重要。

UTC与本地时间

const timestamp = 1704067200000;  // 2024年1月1日 00:00:00 UTC
const date = new Date(timestamp);

// 获取UTC组件
console.log('UTC年份:', date.getUTCFullYear());        // 2024
console.log('UTC月份:', date.getUTCMonth() + 1);      // 1
console.log('UTC日期:', date.getUTCDate());           // 1
console.log('UTC小时:', date.getUTCHours());          // 0

// 获取本地组件(取决于您的时区)
console.log('本地年份:', date.getFullYear());         // 2024
console.log('本地月份:', date.getMonth() + 1);        // 1(或不同)
console.log('本地日期:', date.getDate());             // 1(或不同)
console.log('本地小时:', date.getHours());            // 0(或不同)

转换到特定时区

const timestamp = 1704067200000;
const date = new Date(timestamp);

// 使用Intl.DateTimeFormat在不同时区显示
const timezones = ['America/New_York', 'Europe/London', 'Asia/Shanghai'];

timezones.forEach(tz => {
    const formatter = new Intl.DateTimeFormat('zh-CN', {
        timeZone: tz,
        year: 'numeric',
        month: '2-digit',
        day: '2-digit',
        hour: '2-digit',
        minute: '2-digit',
        second: '2-digit',
        timeZoneName: 'short'
    });
    console.log(`${tz}:`, formatter.format(date));
});

// 输出:
// America/New_York: 2023/12/31 19:00:00 EST
// Europe/London: 2024/01/01 00:00:00 GMT
// Asia/Shanghai: 2024/01/01 08:00:00 GMT+8

时区偏移

const date = new Date();

// 获取时区偏移(分钟)
const offsetMinutes = date.getTimezoneOffset();
console.log('偏移(分钟):', offsetMinutes);  // 例如,-480表示UTC+8

// 转换为小时
const offsetHours = -offsetMinutes / 60;
console.log('偏移(小时):', offsetHours);  // 例如,8表示UTC+8

// 格式化偏移为字符串
const sign = offsetHours >= 0 ? '+' : '-';
const hours = String(Math.abs(Math.floor(offsetHours))).padStart(2, '0');
const minutes = String(Math.abs((offsetHours % 1) * 60)).padStart(2, '0');
console.log(`UTC${sign}${hours}:${minutes}`);  // 例如,"UTC+08:00"

步骤6:常见陷阱和解决方案

陷阱1:秒vs毫秒

// ❌ 错误:假设所有时间戳都是毫秒
const wrongDate = new Date(1704067200);  // 当作毫秒处理
console.log(wrongDate.toISOString());     // 1970-01-20T17:27:47.200Z(错误!)

// ✅ 正确:正确检查和转换
const secondsTimestamp = 1704067200;
const correctDate = new Date(secondsTimestamp * 1000);
console.log(correctDate.toISOString());   // 2024-01-01T00:00:00.000Z(正确!)

陷阱2:月份从零开始索引

// ❌ 错误:对月份使用1-12
const wrongDate = new Date(2024, 1, 1);  // 创建2月1日,而不是1月1日
console.log(wrongDate.toDateString());   // Thu Feb 01 2024

// ✅ 正确:对月份使用0-11
const correctDate = new Date(2024, 0, 1);  // 创建1月1日
console.log(correctDate.toDateString());   // Mon Jan 01 2024

陷阱3:日期字符串的时区问题

// 不同的字符串格式表现不同!

// 带'Z'的ISO 8601 - 始终为UTC
const utcDate = new Date('2024-01-01T00:00:00Z');
console.log(utcDate.toISOString());  // 2024-01-01T00:00:00.000Z

// 不带'Z'的ISO 8601 - 当作本地时区处理
const localDate = new Date('2024-01-01T00:00:00');
console.log(localDate.toISOString());  // 取决于您的时区

// 仅日期格式 - 当作本地时区午夜处理
const dateOnly = new Date('2024-01-01');
console.log(dateOnly.toISOString());  // 通常为本地午夜

// ✅ 最佳实践:始终使用带'Z'的ISO 8601表示UTC
const safeDate = new Date('2024-01-01T00:00:00.000Z');

陷阱4:无效日期

// 无效日期可能导致静默错误
const invalidDate = new Date('不是日期');
console.log(invalidDate);                 // Invalid Date
console.log(invalidDate.getTime());       // NaN

// ✅ 最佳实践:始终验证
function isValidDate(date) {
    return date instanceof Date && !isNaN(date.getTime());
}

const date1 = new Date('2024-01-01');
const date2 = new Date('invalid');

console.log(isValidDate(date1));  // true
console.log(isValidDate(date2));  // false

步骤7:实际示例

示例1:显示"多久以前"格式

function timeAgo(timestamp) {
    const now = Date.now();
    const secondsAgo = Math.floor((now - timestamp) / 1000);

    if (secondsAgo < 60) {
        return `${secondsAgo}秒前`;
    } else if (secondsAgo < 3600) {
        const minutes = Math.floor(secondsAgo / 60);
        return `${minutes}分钟前`;
    } else if (secondsAgo < 86400) {
        const hours = Math.floor(secondsAgo / 3600);
        return `${hours}小时前`;
    } else {
        const days = Math.floor(secondsAgo / 86400);
        return `${days}天前`;
    }
}

// 使用方法
console.log(timeAgo(Date.now() - 30000));      // "30秒前"
console.log(timeAgo(Date.now() - 300000));     // "5分钟前"
console.log(timeAgo(Date.now() - 7200000));    // "2小时前"
console.log(timeAgo(Date.now() - 172800000));  // "2天前"

示例2:API响应处理器

// 典型的带时间戳的API响应
const apiResponse = {
    created_at: 1704067200,     // 秒
    updated_at: 1704153600000,  // 毫秒(混合精度!)
    expires_at: "2024-01-10T00:00:00Z"  // ISO 8601字符串
};

// 将所有转换为Date对象
function parseApiTimestamps(response) {
    return {
        created: new Date(response.created_at * 1000),  // 转换秒
        updated: new Date(response.updated_at),          // 已经是毫秒
        expires: new Date(response.expires_at)           // 解析ISO字符串
    };
}

const dates = parseApiTimestamps(apiResponse);
console.log('创建:', dates.created.toLocaleDateString());
console.log('更新:', dates.updated.toLocaleDateString());
console.log('过期:', dates.expires.toLocaleDateString());

示例3:日期范围验证器

function isWithinRange(timestamp, startDate, endDate) {
    const date = new Date(timestamp);
    const start = new Date(startDate);
    const end = new Date(endDate);

    return date >= start && date <= end;
}

// 使用方法
const eventTimestamp = 1704067200000;  // 2024年1月1日
const rangeStart = '2024-01-01';
const rangeEnd = '2024-12-31';

console.log(isWithinRange(eventTimestamp, rangeStart, rangeEnd));  // true

用于高级用例的流行库

对于生产应用,请考虑这些库:

date-fns(推荐)

import { format, parseISO, formatDistance } from 'date-fns';
import { zhCN } from 'date-fns/locale';

// 格式化时间戳
const timestamp = 1704067200000;
const formatted = format(timestamp, 'PPP', { locale: zhCN });
console.log(formatted);  // "2024年1月1日"

// 多久以前
const distance = formatDistance(timestamp, Date.now(), { 
    addSuffix: true,
    locale: zhCN 
});
console.log(distance);  // "2天前"

Luxon(现代、时区感知)

import { DateTime } from 'luxon';

// 从时间戳
const dt = DateTime.fromMillis(1704067200000);
console.log(dt.toISO());  // "2024-01-01T00:00:00.000Z"

// 时区转换
const shanghai = dt.setZone('Asia/Shanghai');
console.log(shanghai.toFormat('yyyy-MM-dd HH:mm:ss'));

总结

您已经学会了如何:

  • ✅ 使用Date.now()获取当前时间戳
  • ✅ 将时间戳转换为Date对象
  • ✅ 将Date对象转换回时间戳
  • ✅ 格式化日期以供显示
  • ✅ 处理不同的时间戳精度
  • ✅ 处理时区
  • ✅ 避免常见陷阱

相关工具

使用我们的免费工具练习所学内容:

下一步


最后更新:2025年1月