- TypeScript 76.4%
- JavaScript 17.4%
- Shell 6.2%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
All checks were successful
git-ci/decimal-format/pipeline/head This commit looks good
|
||
| .jenkins | ||
| .gitignore | ||
| decimal-format.test.mjs | ||
| decimal-format.ts | ||
| java-reference.tsv | ||
| Jenkinsfile | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
DecimalFormat for TypeScript
A dependency-free module implementing Java-style number patterns. Copy decimal-format.ts into your project. Requires an ES2022-compatible runtime (BigInt, DataView and Unicode property escapes).
import { DecimalFormat, formatNumber, parseNumber } from './decimal-format';
const amount = new DecimalFormat('#,##0.00;(#,##0.00)');
amount.format(-1234.5); // '(1,234.50)'
amount.parse('(1,234.50)'); // -1234.5
formatNumber(0.125, '0.0%'); // '12.5%'
parseNumber('12.5%', '0.0%'); // 0.125
new DecimalFormat('0.###E0').format(1234); // '1.234E3'
amount.parsePrefix('1,234.50 remaining'); // { value: 1234.5, index: 8 }
Supported features include 0 and # digit placeholders, decimal and grouping separators, positive/negative subpatterns, quoted affixes and doubled apostrophes, percent/per-mille scaling, currency signs (¤ and ¤¤), scientific/engineering notation, half-even rounding, negative zero, NaN, infinity and customizable output symbols. The final grouping interval repeats, as in Java. Negative subpatterns supply affixes; the positive subpattern controls numeric formatting.
const european = new DecimalFormat('#,##0.00', {
decimalSeparator: ',',
groupingSeparator: '.',
});
european.format(1234.5); // '1.234,50'
european.parse('1.234,50'); // 1234.5
Patterns always use the non-localized Java syntax, regardless of symbol overrides. For currency patterns, set monetaryDecimalSeparator and monetaryGroupingSeparator separately. Currency defaults are $ / USD; no currency conversion or automatic locale selection occurs. zeroDigit configures ten consecutive output digits; parsing additionally recognizes Unicode decimal digits.
parse requires a complete match and throws SyntaxError on failure. parsePrefix(text, start?) returns { value, index } or null, with JavaScript UTF-16 indexes. It does not skip whitespace unless the pattern includes it. Grouping is permissive, and pattern digit counts do not restrict parsing. Invalid patterns throw during construction.
Compatibility scope
This is a practical pattern implementation, not a complete port of Java's DecimalFormat API. It accepts and returns JavaScript number, so it does not preserve arbitrary-precision integers or decimals. It has no BigDecimal/BigInteger overloads, localized-pattern API, mutable Java setters, parse-integer-only mode, or selectable rounding modes. Patterns require a numeric section and are limited to 1,000 digit placeholders. Ambiguous or overlapping custom symbols/affixes should be avoided. Java's less common pattern acceptance and ambiguous parsing behavior are not guaranteed to match. IEEE-754 rounding edge cases can vary across Java versions.
The implementation uses the exact binary value for half-even rounding after applying percentage/per-mille multiplication. Thus decimal-looking inputs such as 2.675 can format to 2.67, reflecting the stored binary number.
Syntax reference: Oracle DecimalFormat documentation.
Validation
Run npm test with Node 22.18+ (native TypeScript stripping). The suite includes feature tests and 80 formatting fixtures captured from OpenJDK 11 using US symbols. These fixtures are regression coverage, not proof of complete Java equivalence. A strict tsconfig.json is included for projects with TypeScript installed; run tsc to emit JavaScript and declarations. The delivered tests were executed with Node 25; a standalone TypeScript compiler was unavailable in the creation environment.