This document details important limitations and considerations you should be aware of when using the Currency.js library.
- 1. Two Decimal Places Limitation
- 2. Internal Rounding Behavior
- 3. Preference for the allocate Method
- 4. Chained Operations Processing
- 5. Compatibility with Different Locales
- 6. Float Precision Issues
- 7. Immutability Side Effects
- 8. Currency Symbol Inconsistencies
- 9. Time Zone Considerations
- 10. Internationalization Testing
The Currency.js library has been optimized to work with monetary values containing up to two decimal places. Using the library with values that have more than two decimal places may result in inaccuracies.
// ✅ Recommended: values with up to 2 decimal places
const price1 = Money(19.99);
const price2 = Money(100.5);
// ⚠️ Not recommended: values with more than 2 decimal places
const price3 = Money(19.999); // Will be rounded to 20.00
const price4 = Money(100.505); // Will be rounded to 100.51The library performs internal rounding to preserve the precision of operations. It's important to be aware of these rounding strategies when performing calculations in sequence.
// Example of internal rounding
const price = Money(10.565); // Internally rounded to 10.57
// Rounding in mathematical operations
const resultA = Money(10.51).times(0.33); // 3.47 (not 3.4683)
const resultB = Money(99.99).dividedBy(3); // 33.33 (not 33.33...)
// To visualize the rounding behavior
const value = Money(10.516);
console.log(value.value); // 10.52 (rounded)
console.log(value.cents); // 1052 (value in cents after rounding)To distribute values with greater precision (such as in payment installments), always prefer to use the allocate method instead of dividedBy. The allocate method ensures that the sum of the parts is exactly equal to the original value, avoiding rounding problems.
// ❌ Less precise: using dividedBy for installments
const totalAmount = Money(100);
const installments = 3;
const eachInstallment = totalAmount.dividedBy(installments); // 33.33
const totalSum = eachInstallment.times(installments); // 99.99 (loss of 0.01)
// ✅ More precise: using allocate for installments
const totalAmount = Money(100);
const installments = totalAmount.allocate(3); // [33.34, 33.33, 33.33]
console.log(installments[0].format()); // $33.34
console.log(installments[1].format()); // $33.33
console.log(installments[2].format()); // $33.33
// The sum of the installments is exactly equal to the original value
const totalSum = installments.reduce(
(sum, amount) => sum.plus(amount),
Money(0)
); // 100.00When chaining multiple operations, be aware that each operation creates a new Money instance and that rounding is applied at each step:
// Example of chained operations with intermediate rounding
const result = Money(33.33)
.times(1.05) // 34.9965 -> rounded to 35.00
.minus(0.5) // 34.50
.dividedBy(3); // 11.50
// For critical operations requiring absolute precision,
// consider reducing the number of chained operationsWhen working with different regional settings (locales), make sure to provide both the correct currency code and locale to ensure proper formatting:
// Incorrect combinations may lead to inaccurate formatting
const amount = Money(1234.56);
// ✅ Correct: matching currency and locale
amount.format({ currencyCode: 'BRL', locale: 'pt-BR' }); // R$ 1.234,56
// ⚠️ Be careful: different currency and locale
amount.format({ currencyCode: 'USD', locale: 'pt-BR' }); // US$ 1.234,56JavaScript's floating-point limitations remain a concern even with dedicated money handling libraries. Currency.js mitigates these issues by storing values as integers (cents), but be aware of potential precision problems with very large numbers:
// Be careful with very large monetary values
const veryLargeAmount = Money(9007199254740991); // Maximum safe integer in JavaScript
const doubledAmount = veryLargeAmount.times(2); // May cause precision issues
// For extremely large values, consider alternative solutions or use BigInt-based librariesWhile immutability is beneficial for preventing unintended modifications, it can lead to increased memory usage when performing many operations in succession:
// Each operation creates a new Money instance
let result = Money(100);
// This creates 1000 different Money instances
for (let i = 0; i < 1000; i++) {
result = result.plus(0.01);
}
// For intensive calculations with many iterations, consider using
// the Calculator API instead of chaining many operationsCurrency symbols may be displayed differently depending on the user's browser and operating system:
// The same code might produce different displays on different systems
const price = Money(99.99, { currencyCode: 'USD', locale: 'en-US' });
// On some systems: $99.99
// On some systems: US$99.99
// On some systems: 99.99 USD
// For critical display requirements, always test on target platformsWhen working with date-based financial calculations (like interest or prorated billing), be aware of time zone differences:
// Calculation that might be affected by time zones
const subscriptionStartDate = new Date('2025-05-15T00:00:00Z');
const today = new Date();
// Days calculation might vary depending on the user's time zone
const daysSinceStart = Math.floor((today - subscriptionStartDate) / (1000 * 60 * 60 * 24));
const dailyRate = Money(30).dividedBy(30);
const proRatedAmount = dailyRate.times(daysSinceStart);
// Always normalize dates to a specific time zone for financial calculationsAlways test your application with various locale settings to ensure proper formatting:
// Test with multiple locales to ensure proper formatting
const amount = Money(1234.56);
// Test various formats and check for unexpected behaviors
const formats = [
amount.format({ currencyCode: 'USD', locale: 'en-US' }),
amount.format({ currencyCode: 'EUR', locale: 'de-DE' }),
amount.format({ currencyCode: 'JPY', locale: 'ja-JP' }),
amount.format({ currencyCode: 'BRL', locale: 'pt-BR' }),
amount.format({ currencyCode: 'INR', locale: 'en-IN' }),
amount.format({ currencyCode: 'AED', locale: 'ar-AE' }), // Right-to-left language
];
// Verify that all formats display correctly in your application