Skip to content

日期与货币格式

不同地区和文化对日期、时间、数字和货币的显示格式有不同的约定。美国使用 MM/DD/YYYY,中国使用 YYYY-MM-DD 或 YYYY年MM月DD日;货币符号的位置和分隔符也各不相同。本节将详细介绍 JavaScript 的 Intl API、如何使用 data 属性传递原始值,以及实现本地化显示的最佳实践。

前置知识

阅读本节前,建议先了解:多语言页面设计

日期格式差异

各地区日期格式

地区格式示例
中国YYYY-MM-DD2024-01-15
中国(中文)YYYY年MM月DD日2024年1月15日
美国MM/DD/YYYY01/15/2024
英国DD/MM/YYYY15/01/2024
日本YYYY/MM/DD2024/01/15
ISO 8601YYYY-MM-DD2024-01-15

Intl API

Intl.DateTimeFormat

javascript
// 基本日期格式化
const date = new Date('2024-01-15T10:30:00');

// 中文格式
console.log(new Intl.DateTimeFormat('zh-CN').format(date));
// 输出: 2024/1/15

// 美国格式
console.log(new Intl.DateTimeFormat('en-US').format(date));
// 输出: 1/15/2024

// 日本格式
console.log(new Intl.DateTimeFormat('ja-JP').format(date));
// 输出: 2024/1/15

日期格式选项

javascript
const date = new Date('2024-01-15T10:30:00');

// 完整日期
const fullDate = new Intl.DateTimeFormat('zh-CN', {
  year: 'numeric',
  month: 'long',
  day: 'numeric',
  weekday: 'long'
}).format(date);
// 输出: 2024年1月15日星期一

const fullDateEn = new Intl.DateTimeFormat('en-US', {
  year: 'numeric',
  month: 'long',
  day: 'numeric',
  weekday: 'long'
}).format(date);
// 输出: Monday, January 15, 2024

// 仅时间
const time = new Intl.DateTimeFormat('zh-CN', {
  hour: 'numeric',
  minute: 'numeric',
  second: 'numeric',
  hour12: false
}).format(date);
// 输出: 10:30:00

const timeEn = new Intl.DateTimeFormat('en-US', {
  hour: 'numeric',
  minute: 'numeric',
  second: 'numeric',
  hour12: true
}).format(date);
// 输出: 10:30:00 AM

时间相对格式

javascript
const rtf = new Intl.RelativeTimeFormat('zh-CN', { numeric: 'auto' });

console.log(rtf.format(-1, 'day'));
// 输出: 昨天

console.log(rtf.format(-2, 'day'));
// 输出: 前天

console.log(rtf.format(1, 'day'));
// 输出: 明天

console.log(rtf.format(7, 'day'));
// 输出: 7天后

console.log(rtf.format(-1, 'hour'));
// 输出: 1小时前

console.log(rtf.format(-1, 'month'));
// 输出: 上个月

Intl.NumberFormat

javascript
// 数字格式化
const number = 1234567.89;

// 中文数字
console.log(new Intl.NumberFormat('zh-CN').format(number));
// 输出: 1,234,567.89

// 德国数字(逗号作小数点)
console.log(new Intl.NumberFormat('de-DE').format(number));
// 输出: 1.234.567,89

// 印度数字
console.log(new Intl.NumberFormat('en-IN').format(number));
// 输出: 12,34,567.89

// 百分比
console.log(new Intl.NumberFormat('zh-CN', {
  style: 'percent'
}).format(0.85));
// 输出: 85%

Intl.NumberFormat - 货币

javascript
const price = 299.99;

// 人民币
console.log(new Intl.NumberFormat('zh-CN', {
  style: 'currency',
  currency: 'CNY'
}).format(price));
// 输出: ¥299.99

// 美元
console.log(new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD'
}).format(price));
// 输出: $299.99

// 欧元(德国格式)
console.log(new Intl.NumberFormat('de-DE', {
  style: 'currency',
  currency: 'EUR'
}).format(price));
// 输出: 299,99 €

// 日元
console.log(new Intl.NumberFormat('ja-JP', {
  style: 'currency',
  currency: 'JPY'
}).format(price));
// 输出: ¥300(日元通常没有小数)

Intl.ListFormat

javascript
const items = ['HTML', 'CSS', 'JavaScript'];

// 中文列表
console.log(new Intl.ListFormat('zh-CN').format(items));
// 输出: HTML、CSS和JavaScript

// 英文列表
console.log(new Intl.ListFormat('en-US').format(items));
// 输出: HTML, CSS, and JavaScript

// 英文列表(不同风格)
console.log(new Intl.ListFormat('en-US', { type: 'disjunction' }).format(items));
// 输出: HTML, CSS, or JavaScript

data 属性传递原始值

使用 data-* 属性存储原始数据值,然后通过 JavaScript 格式化为本地化显示:

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>本地化日期与货币示例</title>
  <style>
    body { font-family: -apple-system, sans-serif; max-width: 800px; margin: 0 auto; padding: 2rem; }
    .product { border: 1px solid #e0e0e0; padding: 1rem; border-radius: 8px; margin: 1rem 0; }
    .price { font-size: 1.5rem; font-weight: bold; color: #0066cc; }
    .date { color: #666; font-size: 0.875rem; }
    table { width: 100%; border-collapse: collapse; }
    th, td { border: 1px solid #ddd; padding: 0.5rem; text-align: left; }
  </style>
</head>
<body>
  <h1>产品列表</h1>

  <!-- 使用 data 属性存储原始值 -->
  <div class="product">
    <h2>无线蓝牙耳机</h2>
    <!-- 存储原始价格和货币 -->
    <div class="price" data-price="299.99" data-currency="CNY"></div>
    <div class="date" data-date="2024-01-15T10:30:00"></div>
  </div>

  <div class="product">
    <h2>机械键盘</h2>
    <div class="price" data-price="499.00" data-currency="CNY"></div>
    <div class="date" data-date="2024-01-10T08:00:00"></div>
  </div>

  <!-- 订单表格 -->
  <table>
    <thead>
      <tr>
        <th>商品</th>
        <th>单价</th>
        <th>数量</th>
        <th>小计</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>无线蓝牙耳机</td>
        <td data-price="299.99" data-currency="CNY"></td>
        <td data-quantity="2"></td>
        <td data-price="599.98" data-currency="CNY"></td>
      </tr>
    </tbody>
  </table>

  <script>
    // 获取用户语言偏好
    const userLang = navigator.language || 'zh-CN';

    // 格式化货币
    function formatPrice(price, currency) {
      return new Intl.NumberFormat(userLang, {
        style: 'currency',
        currency: currency,
        minimumFractionDigits: 2,
        maximumFractionDigits: 2
      }).format(price);
    }

    // 格式化日期
    function formatDate(dateString) {
      const date = new Date(dateString);
      return new Intl.DateTimeFormat(userLang, {
        year: 'numeric',
        month: 'long',
        day: 'numeric'
      }).format(date);
    }

    // 格式化数字
    function formatNumber(num) {
      return new Intl.NumberFormat(userLang).format(num);
    }

    // 格式化所有价格元素
    document.querySelectorAll('[data-price]').forEach(el => {
      const price = parseFloat(el.dataset.price);
      const currency = el.dataset.currency || 'CNY';
      el.textContent = formatPrice(price, currency);
    });

    // 格式化所有日期元素
    document.querySelectorAll('[data-date]').forEach(el => {
      el.textContent = formatDate(el.dataset.date);
    });

    // 格式化数量
    document.querySelectorAll('[data-quantity]').forEach(el => {
      el.textContent = formatNumber(parseInt(el.dataset.quantity));
    });
  </script>
</body>
</html>

HTML time 元素

使用 <time> 元素为日期和时间提供机器可读的格式:

html
<!-- 基本日期 -->
<time datetime="2024-01-15">2024年1月15日</time>

<!-- 带时间 -->
<time datetime="2024-01-15T10:30:00+08:00">
  2024年1月15日 上午10:30
</time>

<!-- 相对时间 -->
<time datetime="2024-01-15">昨天</time>

<!-- 时间范围 -->
<time datetime="PT2H30M">2小时30分钟</time>

<!-- 发布时间(用于 SEO) -->
<article>
  <h1>HTML5 教程</h1>
  <time datetime="2024-01-15" pubdate>
    发布于 2024年1月15日
  </time>
</article>

实战示例:多格式日期货币页面

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>本地化格式示例</title>
  <style>
    body { font-family: -apple-system, sans-serif; max-width: 800px; margin: 0 auto; padding: 2rem; }
    .format-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem; }
    .format-card {
      border: 1px solid #e0e0e0; border-radius: 8px; padding: 1rem; text-align: center;
    }
    .format-card h3 { font-size: 0.875rem; color: #666; margin: 0 0 0.5rem; }
    .format-card .value { font-size: 1.25rem; font-weight: bold; }
  </style>
</head>
<body>
  <h1>本地化格式对比</h1>

  <div class="format-grid">
    <div class="format-card">
      <h3>中文日期</h3>
      <div class="value" id="date-zh-CN"></div>
    </div>
    <div class="format-card">
      <h3>美国日期</h3>
      <div class="value" id="date-en-US"></div>
    </div>
    <div class="format-card">
      <h3>英国日期</h3>
      <div class="value" id="date-en-GB"></div>
    </div>
    <div class="format-card">
      <h3>日本日期</h3>
      <div class="value" id="date-ja-JP"></div>
    </div>
  </div>

  <h2>货币格式</h2>
  <div class="format-grid">
    <div class="format-card">
      <h3>人民币</h3>
      <div class="value" id="currency-CNY"></div>
    </div>
    <div class="format-card">
      <h3>美元</h3>
      <div class="value" id="currency-USD"></div>
    </div>
    <div class="format-card">
      <h3>欧元</h3>
      <div class="value" id="currency-EUR"></div>
    </div>
    <div class="format-card">
      <h3>日元</h3>
      <div class="value" id="currency-JPY"></div>
    </div>
  </div>

  <script>
    const date = new Date('2024-01-15T14:30:00');
    const price = 1234.56;

    // 日期格式
    ['zh-CN', 'en-US', 'en-GB', 'ja-JP'].forEach(locale => {
      const el = document.getElementById('date-' + locale);
      el.textContent = new Intl.DateTimeFormat(locale, {
        year: 'numeric', month: 'long', day: 'numeric', weekday: 'long'
      }).format(date);
    });

    // 货币格式
    const currencyMap = { CNY: 'zh-CN', USD: 'en-US', EUR: 'de-DE', JPY: 'ja-JP' };
    Object.entries(currencyMap).forEach(([currency, locale]) => {
      const el = document.getElementById('currency-' + currency);
      el.textContent = new Intl.NumberFormat(locale, {
        style: 'currency', currency
      }).format(price);
    });
  </script>
</body>
</html>

注意事项

  1. 使用 data 属性存储原始值:不要在 HTML 中硬编码格式化后的值
  2. 使用 Intl API 而非手动拼接:避免手动拼接日期和货币字符串
  3. time 元素使用 ISO 8601datetime 属性使用标准格式
  4. 考虑用户时区:日期时间显示需要考虑时区
  5. 货币值不要四舍五入:保持精度直到最终显示

最佳实践

  • 使用 Intl API 进行所有日期、数字和货币的格式化
  • 在 HTML 中使用 data-* 属性存储原始数据值
  • 使用 <time> 元素提供机器可读的日期
  • 根据用户的语言偏好动态格式化
  • 货币符号放置位置遵循地区惯例
  • 考虑相对时间格式(如"3天前")提升可读性

下一节

继续学习:代码风格指南

参考链接