Use Cases

Währungsformatierung mit Claude Code implementieren

Erfahren Sie, wie Sie Währungsformatierung mit Claude Code implementieren. Mit praktischen Codebeispielen.

Währungsformatierung mit Claude Code korrekt implementieren

In E-Commerce-Websites, Buchhaltungs-Apps und internationalen Services ist eine korrekte Währungsformatierung unverzichtbar. Die Regeln für Dezimalstellen, Tausendertrennzeichen und Währungssymbole unterscheiden sich je nach Land und Währung. Eigene Formatierungen führen schnell zu Fehlern. Mit Claude Code können Sie unter Nutzung von Intl.NumberFormat und spezialisierten Bibliotheken eine robuste Implementierung effizient aufbauen.

Intl.NumberFormat nutzen

> Erstelle ein Währungsformatierungs-Utility für mehrere Währungen.
> Unterstützung für JPY, USD und EUR.
> Einschließlich Locale-spezifischer Anzeige, Wechselkursumrechnung und Betragsvalidierung.
// src/lib/currency.ts

export type CurrencyCode = 'JPY' | 'USD' | 'EUR' | 'GBP' | 'CNY' | 'KRW';

interface FormatOptions {
  currency: CurrencyCode;
  locale?: string;
  compact?: boolean;      // Kurzdarstellung wie "1,2k"
  showSign?: boolean;     // +/- Vorzeichen anzeigen
}

/**
 * Währung formatieren
 */
export function formatCurrency(
  amount: number,
  options: FormatOptions
): string {
  const { currency, locale = 'de-DE', compact = false, showSign = false } = options;

  const formatter = new Intl.NumberFormat(locale, {
    style: 'currency',
    currency,
    notation: compact ? 'compact' : 'standard',
    signDisplay: showSign ? 'exceptZero' : 'auto',
    // Dezimalwährungen mit 2 Nachkommastellen, JPY/KRW mit 0 (automatische Erkennung)
  });

  return formatter.format(amount);
}

// Verwendungsbeispiele
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万"

Hinweise zur Währungsberechnung

// src/lib/currency-math.ts

/**
 * Um Gleitkommafehler zu vermeiden, wird in der kleinsten Währungseinheit (ganzzahlig) gerechnet
 * JPY: 1 Yen = 1 | USD: 1 Cent = 1 | EUR: 1 Cent = 1
 */
export class Money {
  constructor(
    private readonly amountInMinorUnit: number,
    private readonly currency: CurrencyCode
  ) {}

  // Anzahl der Nachkommastellen für Cent/Yen
  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(`Unterschiedliche Währungen: ${this.currency} und ${other.currency}`);
    }
  }
}

// Verwendungsbeispiel
const price = Money.fromMajorUnit(1980, 'JPY');
const tax = price.multiply(0.1);
const total = price.add(tax);
console.log(total.format()); // "¥2,178"

Wechselkursumrechnung

// 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> {
  // Cache wiederverwenden, wenn unter 1 Stunde alt
  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,
  };
}

Währungseingabe-Komponente

// 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('de-DE', {
    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>
  );
}

Die Falle der Gleitkommazahlen

Das Problem, dass in JavaScript 0.1 + 0.2 === 0.30000000000000004 ergibt, ist bekannt. Bei Währungsberechnungen gilt die Regel, immer in der kleinsten Einheit (Cent/Yen) ganzzahlig zu rechnen und erst bei der Anzeige in Dezimalzahlen umzuwandeln.

Verwandte Artikel

Zur Datumsformatierung siehe Datum und Uhrzeit handhaben, zur Internationalisierung allgemein den i18n-Implementierungsleitfaden.

Die detaillierte Spezifikation von Intl.NumberFormat finden Sie bei MDN (developer.mozilla.org/Intl/NumberFormat).

#Claude Code #Währung #Formatierung #Intl #Internationalisierung