日期与货币格式
不同地区和文化对日期、时间、数字和货币的显示格式有不同的约定。美国使用 MM/DD/YYYY,中国使用 YYYY-MM-DD 或 YYYY年MM月DD日;货币符号的位置和分隔符也各不相同。本节将详细介绍 JavaScript 的 Intl API、如何使用 data 属性传递原始值,以及实现本地化显示的最佳实践。
前置知识
阅读本节前,建议先了解:多语言页面设计
日期格式差异
各地区日期格式
| 地区 | 格式 | 示例 |
|---|---|---|
| 中国 | YYYY-MM-DD | 2024-01-15 |
| 中国(中文) | YYYY年MM月DD日 | 2024年1月15日 |
| 美国 | MM/DD/YYYY | 01/15/2024 |
| 英国 | DD/MM/YYYY | 15/01/2024 |
| 日本 | YYYY/MM/DD | 2024/01/15 |
| ISO 8601 | YYYY-MM-DD | 2024-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 JavaScriptdata 属性传递原始值
使用 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>注意事项
- 使用 data 属性存储原始值:不要在 HTML 中硬编码格式化后的值
- 使用 Intl API 而非手动拼接:避免手动拼接日期和货币字符串
- time 元素使用 ISO 8601:
datetime属性使用标准格式 - 考虑用户时区:日期时间显示需要考虑时区
- 货币值不要四舍五入:保持精度直到最终显示
最佳实践
- 使用
IntlAPI 进行所有日期、数字和货币的格式化 - 在 HTML 中使用
data-*属性存储原始数据值 - 使用
<time>元素提供机器可读的日期 - 根据用户的语言偏好动态格式化
- 货币符号放置位置遵循地区惯例
- 考虑相对时间格式(如"3天前")提升可读性
下一节
继续学习:代码风格指南