如何显示公元前/公元或其他纪元标识?

使用 Intl.DateTimeFormat 的 era 选项显示公元、公元前及其他历法系统的纪元名称

简介

大多数情况下,您处理的日期都属于公历的当前纪元,因此通常无需显示纪元标识。例如,“2024年10月15日”即使不加“公元”也很清楚。但对于两千多年前的历史日期,纪元标识有助于明确年份是在公元前还是公元后。

不同文化也有各自的历法系统和纪元。例如,日本历法以天皇在位划分纪元,如令和、平成。佛历以佛陀涅槃为起点计年。伊斯兰历则以希吉拉(迁徙)为纪元起点。

JavaScript 的 Intl.DateTimeFormat 提供了 era 选项,可用于显示这些纪元标识。该选项不仅适用于公历,也支持其他历法系统,并会根据本地化习惯自动格式化纪元显示。

理解历法系统中的纪元

纪元是指从某一重大事件或起点开始计时的一段时期。公历有两个纪元:公元(AD,拉丁语“主的年份”)表示公元1年之后的日期,公元前(BC)表示公元1年之前的日期。

在显示历史日期时,纪元标识尤为重要。例如,公元500年和公元前500年相差一千年,仅用“500年”会造成歧义,添加纪元标识可以消除这种混淆。

其他历法系统对纪元的定义各不相同。日本历法每逢新天皇即位便更换纪元。佛历自公元前543年起采用单一纪元。每种历法系统都有自己的纪元显示规范。

在公历日期中显示纪元指示符

era 选项接受三个值,用于控制纪元的显示方式。值 long 显示完整的纪元名称。值 short 显示缩写形式。值 narrow 显示最简洁的表示方式。

const date = new Date('2024-10-15');

const long = new Intl.DateTimeFormat('en-US', {
  year: 'numeric',
  month: 'long',
  day: 'numeric',
  era: 'long'
});
console.log(long.format(date)); // "October 15, 2024 Anno Domini"

const short = new Intl.DateTimeFormat('en-US', {
  year: 'numeric',
  month: 'long',
  day: 'numeric',
  era: 'short'
});
console.log(short.format(date)); // "October 15, 2024 AD"

const narrow = new Intl.DateTimeFormat('en-US', {
  year: 'numeric',
  month: 'long',
  day: 'numeric',
  era: 'narrow'
});
console.log(narrow.format(date)); // "October 15, 2024 A"

long 值会在公元日期下显示 "Anno Domini"。short 值会显示 "AD"。narrow 值只显示 "A"。

对于现代日期,纪元指示符通常是多余的,因为默认假定为当前纪元。通常只有在显示历史日期且区分纪元很重要时才会包含纪元信息。

使用纪元指示符格式化公元前日期

JavaScript 通过负数年份或向 Date 构造函数传递负值来表示公元前日期。年份 -500 表示公元前 501 年,年份 -1 表示公元前 2 年,年份 0 表示公元前 1 年。

const bcDate = new Date(-500, 0, 1); // January 1, 501 BC

const long = new Intl.DateTimeFormat('en-US', {
  year: 'numeric',
  month: 'long',
  day: 'numeric',
  era: 'long'
});
console.log(long.format(bcDate)); // "January 1, 501 Before Christ"

const short = new Intl.DateTimeFormat('en-US', {
  year: 'numeric',
  month: 'long',
  day: 'numeric',
  era: 'short'
});
console.log(short.format(bcDate)); // "January 1, 501 BC"

long 值会在公元前日期下显示 "Before Christ"。short 值会显示 "BC"。年份以正数显示,纪元指示符用于区分其是在公元 1 年之前还是之后。

处理公元前日期时需要特别注意,因为 JavaScript Date 对象在处理远古日期时存在局限性。1582 年格里高利历标准化之前的历史日期为近似值,1 年之前的日期采用的是当时并不存在的历法系统。

在日本历中显示纪元

日本历法采用以天皇在位期间更替的年号制度。当前年号为“令和”,自 2019 年开始。前一个年号为“平成”,从 1989 年持续到 2019 年。

你可以在 locale 标识符中使用 Unicode 扩展 -u-ca-japanese 来指定日本历法。

const date = new Date('2024-10-15');

const long = new Intl.DateTimeFormat('ja-JP-u-ca-japanese', {
  year: 'numeric',
  month: 'long',
  day: 'numeric',
  era: 'long'
});
console.log(long.format(date)); // "令和6年10月15日"

const short = new Intl.DateTimeFormat('ja-JP-u-ca-japanese', {
  year: 'numeric',
  month: 'long',
  day: 'numeric',
  era: 'short'
});
console.log(short.format(date)); // "令和6年10月15日"

const narrow = new Intl.DateTimeFormat('ja-JP-u-ca-japanese', {
  year: 'numeric',
  month: 'long',
  day: 'numeric',
  era: 'narrow'
});
console.log(narrow.format(date)); // "R6年10月15日"

longshort 两个值都会显示“令和”以及该年号下的年份。例如,2024 年是令和第 6 年。narrow 值会以紧凑缩写形式显示为“R”。

显示的年份不是公历年,而是当前天皇年号下的纪年。每个年号的年份都从 1 开始重新计数。

在佛历中显示纪元

佛历从公元前 543 年佛陀圆寂之年开始计年。佛历 2567 年对应公历 2024 年。

你可以在 locale 标识符中使用 Unicode 扩展 -u-ca-buddhist 来指定佛历。

const date = new Date('2024-10-15');

const long = new Intl.DateTimeFormat('th-TH-u-ca-buddhist', {
  year: 'numeric',
  month: 'long',
  day: 'numeric',
  era: 'long'
});
console.log(long.format(date)); // "15 ตุลาคม พุทธศักราช 2567"

const short = new Intl.DateTimeFormat('th-TH-u-ca-buddhist', {
  year: 'numeric',
  month: 'long',
  day: 'numeric',
  era: 'short'
});
console.log(short.format(date)); // "15 ตุลาคม พ.ศ. 2567"

long 值会显示“พุทธศักราช”(佛历)作为完整纪元名称。short 值会显示“พ.ศ.”作为缩写形式。2567 年表示佛历年份,对应公历 2024 年。

佛历在泰国、柬埔寨、老挝、缅甸和斯里兰卡等国家广泛使用。

不同本地化环境下的纪元格式差异

不同的本地化环境会对同一纪元使用不同的术语和缩写。公历纪元会以各自语言和风格显示,适应不同 locale 的需求。

const date = new Date('2024-10-15');
const options = {
  year: 'numeric',
  month: 'long',
  day: 'numeric',
  era: 'short'
};

const en = new Intl.DateTimeFormat('en-US', options);
console.log(en.format(date)); // "October 15, 2024 AD"

const fr = new Intl.DateTimeFormat('fr-FR', options);
console.log(fr.format(date)); // "15 octobre 2024 ap. J.-C."

const de = new Intl.DateTimeFormat('de-DE', options);
console.log(de.format(date)); // "15. Oktober 2024 n. Chr."

英语使用 "AD"(Anno Domini,公元)。法语使用 "ap. J.-C."(après Jésus-Christ,意为“耶稣基督之后”)。德语使用 "n. Chr."(nach Christus,意为“基督之后”)。

纪元标识的位置也遵循本地习惯。英语通常将其放在年份之后,而其他语言环境可能有不同的放置方式。

const bcDate = new Date(-500, 0, 1);
const options = {
  year: 'numeric',
  month: 'long',
  day: 'numeric',
  era: 'short'
};

const en = new Intl.DateTimeFormat('en-US', options);
console.log(en.format(bcDate)); // "January 1, 501 BC"

const fr = new Intl.DateTimeFormat('fr-FR', options);
console.log(fr.format(bcDate)); // "1 janvier 501 av. J.-C."

const de = new Intl.DateTimeFormat('de-DE', options);
console.log(de.format(bcDate)); // "1. Januar 501 v. Chr."

法语在公元前日期中使用 "av. J.-C."(avant Jésus-Christ,意为“耶稣基督之前”)。德语使用 "v. Chr."(vor Christus,意为“基督之前”)。

常见用例

显示历史日期时需要纪元标识,以避免混淆。

const battleOfMarathon = new Date(-490, 8, 12); // September 12, 490 BC

const formatter = new Intl.DateTimeFormat('en-US', {
  year: 'numeric',
  month: 'long',
  day: 'numeric',
  era: 'short'
});

console.log(`Battle of Marathon: ${formatter.format(battleOfMarathon)}`);
// "Battle of Marathon: September 12, 490 BC"

在使用不同历法系统的文化语境下显示日期时,需要采用合适的历法和纪元格式。

const date = new Date('2024-10-15');

const japaneseFormatter = new Intl.DateTimeFormat('ja-JP-u-ca-japanese', {
  year: 'numeric',
  month: 'long',
  day: 'numeric',
  era: 'long'
});

console.log(`Japanese date: ${japaneseFormatter.format(date)}`);
// "Japanese date: 令和6年10月15日"

学术或历史写作中通常会同时明确显示 BC 和 AD,以保证跨时间段的一致性。

const dates = [
  new Date(-2500, 0, 1), // 2501 BC
  new Date(-500, 0, 1),  // 501 BC
  new Date(500, 0, 1),   // 500 AD
  new Date(1500, 0, 1)   // 1500 AD
];

const formatter = new Intl.DateTimeFormat('en-US', {
  year: 'numeric',
  era: 'short'
});

dates.forEach(date => {
  console.log(formatter.format(date));
});
// "2501 BC"
// "501 BC"
// "500 AD"
// "1500 AD"

总结

era 选项中,Intl.DateTimeFormat 会显示诸如 AD、BC 或其他历法系统的纪元名称。该选项接受三个值:long 表示完整纪元名称(如 "Anno Domini"),short 表示缩写(如 "AD"),narrow 表示最简形式(如 "A")。

在 JavaScript Date 构造函数中,BC 日期需要使用负数年份。格式化输出时,年份以正数显示,并通过纪元标识区分其是在 1 年之前还是之后。

其他历法系统有各自的纪元。日本历法使用以天皇年号命名的纪元,如令和。佛历以公元前 543 年为纪元起点。可以通过在区域标识符中使用 Unicode 扩展来指定历法系统。

不同的地区会使用不同的术语来表示同一历史时期。英文使用 "AD" 和 "BC",法文使用 "ap. J.-C." 和 "av. J.-C.",德文使用 "n. Chr." 和 "v. Chr."。格式化程序会根据每个地区自动应用相应的术语和位置。