Implementando Formatacao de Moeda com Claude Code
Aprenda sobre implementing currency formatting usando o Claude Code. Inclui exemplos praticos de codigo.
通貨フォーマットをClaude Codeで正しく実装する
ECサイト、会計アプリ、国際対応サービスでは、通貨の正確なフォーマットが不可欠です。小数点、桁区切り、通貨記号のルールは国・通貨ごとに異なるため、自前でフォーマットすると不具合の温床になります。Claude Codeを使えば、Intl.NumberFormatや専用ライブラリを活用した堅牢な実装を効率的に構築できます。
Intl.NumberFormatの活用
> 多通貨対応の通貨フォーマットユーティリティを作って。
> 日本円、USドル、ユーロに対応して。
> ロケール別表示、為替変換、金額のバリデーションも含めて。
// src/lib/currency.ts
export type CurrencyCode = 'JPY' | 'USD' | 'EUR' | 'GBP' | 'CNY' | 'KRW';
interface FormatOptions {
currency: CurrencyCode;
locale?: string;
compact?: boolean; // "1.2万" のような短縮表示
showSign?: boolean; // +/- 符号を表示
}
/**
* 通貨をフォーマットする
*/
export function formatCurrency(
amount: number,
options: FormatOptions
): string {
const { currency, locale = 'en-US', compact = false, showSign = false } = options;
const formatter = new Intl.NumberFormat(locale, {
style: 'currency',
currency,
notation: compact ? 'compact' : 'standard',
signDisplay: showSign ? 'exceptZero' : 'auto',
// 小数通貨は小数点2桁、JPY/KRWは0桁(自動判定)
});
return formatter.format(amount);
}
// Usage example
formatCurrency(1234567, { currency: 'JPY' }); // "¥1,234,567"
formatCurrency(1234.56, { currency: 'USD' }); // "$1,234.56"
formatCurrency(1234.56, { currency: 'EUR', locale: 'de-DE' }); // "1.234,56 €"
formatCurrency(1234567, { currency: 'JPY', compact: true }); // "¥123万"
通貨計算の注意点
// src/lib/currency-math.ts
/**
* 浮動小数点の誤差を避けるため、整数(最小通貨単位)で計算する
* JPY: 1円 = 1 | USD: 1セント = 1 | EUR: 1セント = 1
*/
export class Money {
constructor(
private readonly amountInMinorUnit: number,
private readonly currency: CurrencyCode
) {}
// セント/円の小数桁数
private static decimals(currency: CurrencyCode): number {
return ['JPY', 'KRW'].includes(currency) ? 0 : 2;
}
static fromMajorUnit(amount: number, currency: CurrencyCode): Money {
const decimals = Money.decimals(currency);
const minor = Math.round(amount * Math.pow(10, decimals));
return new Money(minor, currency);
}
toMajorUnit(): number {
const decimals = Money.decimals(this.currency);
return this.amountInMinorUnit / Math.pow(10, decimals);
}
add(other: Money): Money {
this.assertSameCurrency(other);
return new Money(this.amountInMinorUnit + other.amountInMinorUnit, this.currency);
}
subtract(other: Money): Money {
this.assertSameCurrency(other);
return new Money(this.amountInMinorUnit - other.amountInMinorUnit, this.currency);
}
multiply(factor: number): Money {
return new Money(Math.round(this.amountInMinorUnit * factor), this.currency);
}
format(locale?: string): string {
return formatCurrency(this.toMajorUnit(), { currency: this.currency, locale });
}
private assertSameCurrency(other: Money) {
if (this.currency !== other.currency) {
throw new Error(`通貨が異なります: ${this.currency} と ${other.currency}`);
}
}
}
// Usage example
const price = Money.fromMajorUnit(1980, 'JPY');
const tax = price.multiply(0.1);
const total = price.add(tax);
console.log(total.format()); // "¥2,178"
為替レート変換
// src/lib/exchange.ts
interface ExchangeRates {
base: CurrencyCode;
rates: Record<CurrencyCode, number>;
updatedAt: string;
}
let cachedRates: ExchangeRates | null = null;
export async function getExchangeRates(base: CurrencyCode = 'JPY'): Promise<ExchangeRates> {
// キャッシュが1時間以内なら再利用
if (cachedRates && Date.now() - new Date(cachedRates.updatedAt).getTime() < 3600000) {
return cachedRates;
}
const res = await fetch(`https://api.exchangerate-api.com/v4/latest/${base}`);
const data = await res.json();
cachedRates = {
base,
rates: data.rates,
updatedAt: new Date().toISOString(),
};
return cachedRates;
}
export async function convertCurrency(
amount: number,
from: CurrencyCode,
to: CurrencyCode
): Promise<{ converted: number; rate: number }> {
const rates = await getExchangeRates(from);
const rate = rates.rates[to];
return {
converted: Math.round(amount * rate * 100) / 100,
rate,
};
}
通貨入力コンポーネント
// src/components/CurrencyInput.tsx
'use client';
import { useState } from 'react';
interface Props {
value: number;
currency: CurrencyCode;
onChange: (value: number) => void;
}
export function CurrencyInput({ value, currency, onChange }: Props) {
const [displayValue, setDisplayValue] = useState(value.toLocaleString());
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const raw = e.target.value.replace(/[^0-9.-]/g, '');
setDisplayValue(e.target.value);
const num = parseFloat(raw);
if (!isNaN(num)) onChange(num);
};
const handleBlur = () => {
setDisplayValue(value.toLocaleString());
};
const symbol = new Intl.NumberFormat('en-US', {
style: 'currency',
currency,
currencyDisplay: 'narrowSymbol',
}).formatToParts(0).find((p) => p.type === 'currency')?.value || '';
return (
<div className="relative">
<span className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400">{symbol}</span>
<input
type="text"
value={displayValue}
onChange={handleChange}
onBlur={handleBlur}
className="w-full border rounded-lg pl-8 pr-4 py-2 text-right"
inputMode="decimal"
/>
</div>
);
}
浮動小数点の落とし穴
JavaScriptで0.1 + 0.2 === 0.30000000000000004となる問題は有名です。通貨計算では必ず最小単位(セント/円)の整数で扱い、表示時にのみ小数に変換するのが鉄則です。
関連記事
日付のフォーマットは日付・時間の扱い、国際化全般はi18n実装ガイドを参照してください。
Intl.NumberFormatの詳細仕様はMDN(developer.mozilla.org/Intl/NumberFormat)で確認できます。
PDF gratuito: Cheatsheet do Claude Code em 5 minutos
Basta informar seu e-mail e enviamos na hora o cheatsheet em uma página A4.
Cuidamos dos seus dados pessoais e nunca enviamos spam.
Sobre o autor
Masa
Engenheiro apaixonado por Claude Code. Mantém o claudecode-lab.com, uma mídia tech em 10 idiomas com mais de 2.000 páginas.
Artigos relacionados
7 verificações antes de publicar todos os dias um artigo multilíngue sobre Claude Code
Uma checklist prática para publicar artigos multilíngues sobre Claude Code todos os dias sem esquecer idiomas, quebrar CTAs ou deixar páginas antigas no ar.
O que e Codex Automations? Conteudo, analise e deploy com IA enquanto voce dorme
Guia pratico para usar Codex Automations em analytics, artigos, CTA, deploy e monetizacao.
Desenhe Firestore com Claude Code: comece pelas consultas
Workflow prático para Firestore com Claude Code: schema orientado por consultas, índices, custos, regras de segurança e TypeScript.