如何使用括号格式化会计中的负货币金额?

使用 currencySign 选项以会计符号显示负货币值

介绍

财务报表、会计报告和资产负债表通常用括号表示负的货币金额,而不是使用负号。例如,损失五百美元会显示为 ($500.00),而不是 -$500.00。这种惯例使负数金额在视觉上更为显著,减少忽略损失的风险,并符合既定的会计标准。

JavaScript 的 Intl.NumberFormat API 提供了 currencySign 选项,用于以这种会计符号格式化负的货币金额。当您将 currencySign 设置为 "accounting" 时,负值会根据区域设置的惯例自动显示在括号中。

为什么会计符号使用括号

在计算机普及之前,会计中用括号包裹负数金额的做法就已经存在。打印在纸上的负号可能很小、不清晰,或者在浏览数字列时容易被忽略。括号为负值创建了一个清晰的视觉边界,使其一目了然。

括号还可以避免与其他上下文中出现的连字符或破折号混淆。在包含许多行和列的密集财务表格中,括号比单个负号字符更显眼。这种视觉上的区分有助于在阅读、抄录或分析财务数据时防止错误。

这种惯例已成为会计中的标准做法,并且至今仍被广泛使用。大多数会计软件、财务报告和资产负债表都用括号显示负数金额。熟悉财务文件的用户期望这种格式,并认为它比负号更易于阅读。

使用 currencySign 的会计格式

在创建用于货币格式化的 Intl.NumberFormat 实例时,传递值为 "accounting"currencySign 选项。这会告诉格式化器对负数金额使用会计符号。

const formatter = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',
  currencySign: 'accounting'
});

console.log(formatter.format(-1234.56));
// 输出: "($1,234.56)"

console.log(formatter.format(1234.56));
// 输出: "$1,234.56"

负数金额会用括号包裹,而不会显示负号。正数金额则正常显示,不带括号。格式化器会根据值是正数还是负数自动应用适当的会计符号。

currencySign 选项仅影响货币格式化。您必须设置 style: 'currency' 并提供一个 currency 代码,选项才能生效。

比较标准格式和会计格式

默认的货币格式使用负号表示负值。这种标准格式适用于一般用途,而会计格式遵循财务报告惯例。

const standard = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',
  currencySign: 'standard'
});

const accounting = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',
  currencySign: 'accounting'
});

console.log(standard.format(-500));
// 输出: "-$500.00"

console.log(accounting.format(-500));
// 输出: "($500.00)"

标准格式在货币符号前加上负号。会计格式将整个金额(包括货币符号)用括号括起来。对于正值,两种格式的输出相同。

如果省略 currencySign 选项,格式化器会默认使用 "standard" 行为。

const formatter = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD'
});

console.log(formatter.format(-500));
// 输出: "-$500.00"

会计符号在不同地区的差异

不同地区根据本地惯例,将货币符号和括号放置在不同的位置。Intl.NumberFormat API 会自动处理这些差异。

const currencies = [
  { locale: 'en-US', currency: 'USD' },
  { locale: 'de-DE', currency: 'EUR' },
  { locale: 'fr-FR', currency: 'EUR' },
  { locale: 'ja-JP', currency: 'JPY' }
];

currencies.forEach(({ locale, currency }) => {
  const formatter = new Intl.NumberFormat(locale, {
    style: 'currency',
    currency: currency,
    currencySign: 'accounting'
  });

  console.log(`${locale}: ${formatter.format(-1234.56)}`);
});

// 输出:
// en-US: ($1,234.56)
// de-DE: (-1.234,56 €)
// fr-FR: (1 234,56 €)
// ja-JP: (¥-1,235)

每个地区根据其货币符号位置、小数点分隔符、千位分隔符和括号使用的惯例格式化负值。您无需了解这些惯例或手动实现它们。API 会根据地区标识符自动应用正确的格式。

某些地区将负号放在括号内靠近数字的位置,而其他地区将其放在货币符号附近。格式化器会根据地区特定规则处理这些细节。

将会计符号与符号显示选项结合使用

currencySign 选项与 signDisplay 选项配合使用,以控制货币格式中符号的显示方式。这种组合使您可以精确控制正负金额的显示。

const always = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',
  currencySign: 'accounting',
  signDisplay: 'always'
});

console.log(always.format(500));
// 输出:"+$500.00"

console.log(always.format(-500));
// 输出:"($500.00)"

当使用 signDisplay: 'always' 时,正数金额会显示加号,而负数金额仍然使用括号。这使得收益和损失都显而易见。

const never = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',
  currencySign: 'accounting',
  signDisplay: 'never'
});

console.log(never.format(500));
// 输出:"$500.00"

console.log(never.format(-500));
// 输出:"$500.00"

当使用 signDisplay: 'never' 时,正数和负数金额都以相同的方式显示,没有符号或括号。这仅显示数值的大小,而不区分正负。

const exceptZero = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',
  currencySign: 'accounting',
  signDisplay: 'exceptZero'
});

console.log(exceptZero.format(500));
// 输出:"+$500.00"

console.log(exceptZero.format(-500));
// 输出:"($500.00)"

console.log(exceptZero.format(0));
// 输出:"$0.00"

当使用 signDisplay: 'exceptZero' 时,正数金额显示加号,负数金额使用括号,而零则不显示任何符号。这种格式非常适合用于利润和损失报表,强调变化的同时保持零值中立。

何时使用会计格式

在用户期望会计惯例的场景中显示财务数据时,请使用会计格式。这包括财务报表、资产负债表、损益表、利润和损失报告以及会计软件界面。

会计格式使负数金额比标准格式更为显眼。括号创建了一个视觉边界,突出了损失、债务或负余额。这有助于用户在浏览财务数据时快速识别问题区域。

const accountingFormatter = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD',
  currencySign: 'accounting'
});

const accounts = [
  { name: 'Cash', balance: 15000 },
  { name: 'Accounts Receivable', balance: -3500 },
  { name: 'Inventory', balance: 12000 },
  { name: 'Accounts Payable', balance: -8000 }
];

accounts.forEach(account => {
  const formatted = accountingFormatter.format(account.balance);
  console.log(`${account.name}: ${formatted}`);
});

// 输出:
// Cash: $15,000.00
// Accounts Receivable: ($3,500.00)
// Inventory: $12,000.00
// Accounts Payable: ($8,000.00)

括号使负余额更加突出,帮助用户一目了然地识别出负值账户。

在一般电子商务、面向消费者的界面或不适用会计惯例的场景中,请使用标准格式。大多数非会计和金融领域的用户对括号表示法不熟悉,通常期望看到负号来表示负数金额。

const standardFormatter = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'USD'
});

// 用于购物车或退款:
console.log(standardFormatter.format(-25.50));
// 输出:"-$25.50"

当您的受众期望财务报告惯例时,请选择会计格式。当您的受众期望面向消费者的显示时,请选择标准格式。根据用户的期望和数字出现的场景选择合适的格式。

浏览器对会计格式的支持

currencySign: "accounting" 选项在所有现代浏览器中均受支持。Chrome、Edge、Firefox、Safari 及其移动端版本自 2019 年以来发布的版本均支持此功能。

如果需要支持较旧的浏览器,请测试该功能并提供回退方案。

function formatCurrency(amount) {
  try {
    const formatter = new Intl.NumberFormat('en-US', {
      style: 'currency',
      currency: 'USD',
      currencySign: 'accounting'
    });
    return formatter.format(amount);
  } catch (error) {
    // 不支持会计格式的浏览器的回退方案
    const formatter = new Intl.NumberFormat('en-US', {
      style: 'currency',
      currency: 'USD'
    });
    return formatter.format(amount);
  }
}

如果会计格式不可用,此回退方案将返回标准货币格式。实际上,会计格式的支持在现代浏览器中已经足够广泛,对于仅支持现代浏览器的应用程序来说,这种回退方案很少需要。