JSPM

@norbulcz/num-parse

0.1.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 156
  • Score
    100M100P100Q93785F
  • License MIT

Strict, locale-tolerant number parser (US/EU/CH) with validated grouping & currency stripping. Zero deps.

Package Exports

  • @norbulcz/num-parse

Readme

@norbulcz/num-parse

Strict, locale-tolerant number parser (US/EU/CH) with validated grouping. Zero dependencies.

npm version Performance Bundle Size Zero Dependencies

A robust TypeScript library for parsing numbers from strings with support for multiple international formats including US, European, and Swiss number formatting conventions.

Features

  • ๐ŸŒ Multi-locale support: US, EU, and Swiss number formats
  • ๐Ÿ”’ Strict validation: Validates proper thousands separators and decimal points
  • ๐Ÿšซ Zero dependencies: Lightweight with no external dependencies
  • ๐Ÿ“ฆ TypeScript: Full TypeScript support with type definitions
  • ๐Ÿงช Well tested: Comprehensive test suite with 300+ test cases
  • ๐Ÿ“ฑ Modern: ES modules and CommonJS support
  • โšก High Performance: 4.4M+ parses per second

Why Choose @norbulcz/num-parse?

  • Smaller (1.2KB gzipped, zero deps)
  • Stricter (rejects invalid groupings)
  • Locale-flexible (US, EU, Swiss, plain, space grouping, with currency symbols)
  • Safer (never silently misparses into wrong numbers)
  • Simple (no Intl dependency, no polyfills, no moment.js or numeral.js โ€” just a single function)
  • Predictable (invalid input โ†’ returns null, never throws)

Performance

The library is highly optimized for performance:

  • 4.4M+ parses per second on modern hardware
  • 0.0002ms average parse time per operation
  • Pre-compiled regex patterns for maximum efficiency
  • Zero dependencies for minimal bundle impact

Bundle Size

  • ESM: ~1.2KB gzipped
  • CJS: ~1.6KB gzipped
  • Types: ~1.4KB

Installation

npm install @norbulcz/num-parse

Quickstart

import { parseNumber } from '@norbulcz/num-parse';

// US format
parseNumber("1,234.56"); // โ†’ 1234.56

// European format  
parseNumber("1.234,56"); // โ†’ 1234.56

// Swiss format (both apostrophe types)
parseNumber("1'234.56"); // โ†’ 1234.56
parseNumber("1'234.56"); // โ†’ 1234.56 (curly apostrophe)

// Currency symbols (automatically removed)
parseNumber("โ‚ช1,234.56"); // โ†’ 1234.56
parseNumber("1,234.56$"); // โ†’ 1234.56

// Plain numbers (no separators)
parseNumber("1234.56"); // โ†’ 1234.56
parseNumber("1234"); // โ†’ 1234

// Space grouping
parseNumber("1 234.56"); // โ†’ 1234.56
parseNumber("1 234 567.89"); // โ†’ 1234567.89

Usage

import { parseNumber } from '@norbulcz/num-parse';

// US format
parseNumber('1,234.56');     // โ†’ 1234.56
parseNumber('12,345.67');    // โ†’ 12345.67

// European format
parseNumber('1.234,56');     // โ†’ 1234.56
parseNumber('12.345,67');    // โ†’ 12345.67

// Swiss format (apostrophe as thousands separator)
parseNumber("1'234.56");     // โ†’ 1234.56
parseNumber("1'234,56");      // โ†’ 1234.56

// Negative numbers
parseNumber('-1,234.56');    // โ†’ -1234.56
parseNumber('-1.234,56');    // โ†’ -1234.56

// Edge cases
parseNumber('.5');           // โ†’ 0.5
parseNumber(',5');           // โ†’ 0.5
parseNumber('1,000');        // โ†’ 1000
parseNumber('1.000');        // โ†’ 1000

// Currency symbols (automatically removed)
parseNumber('โ‚ช1,234.56');   // โ†’ 1234.56 (Israeli Shekel)
parseNumber('โ‚ฟ0.001');      // โ†’ 0.001 (Bitcoin)
parseNumber('โ‚ฉ1,234.56');   // โ†’ 1234.56 (Korean Won)
parseNumber('โ‚น1,234.56');   // โ†’ 1234.56 (Indian Rupee)
parseNumber('1,234.56$');   // โ†’ 1234.56 (US Dollar at end)
parseNumber('1.234,56โ‚ฌ');   // โ†’ 1234.56 (Euro at end)

// Scientific notation (disabled by default)
parseNumber('1.5e3');        // โ†’ null (disabled by default)
parseNumber('1.5e3', { allowScientific: true }); // โ†’ 1500

// Plain inputs & spaces
parseNumber('3333');         // โ†’ 3333
parseNumber('12345.67');     // โ†’ 12345.67
parseNumber('12345,67');     // โ†’ 12345.67
parseNumber('1 123.34');     // โ†’ 1123.34
parseNumber('2 276,00');     // โ†’ 2276 (NBSP)

// Invalid inputs return null
parseNumber('invalid');      // โ†’ null
parseNumber('1,23,456');     // โ†’ null (invalid grouping)
parseNumber("12'34");        // โ†’ null (invalid apostrophe grouping)
parseNumber('123.');         // โ†’ null (trailing decimal)
parseNumber('');             // โ†’ null

Supported Formats

US Format

  • Thousands separator: comma (,)
  • Decimal separator: period (.)
  • Examples: 1,234.56, 12,345.67

European Format

  • Thousands separator: period (.)
  • Decimal separator: comma (,)
  • Examples: 1.234,56, 12.345,67

Swiss Format

  • Thousands separator: apostrophe (')
  • Decimal separator: period (.) or comma (,)
  • Examples: 1'234.56, 1'234,56

Currency Symbol Support

  • Automatically removes all Unicode currency symbols using the \p{Sc} class
  • Supports: $, โ‚ฌ, ยฃ, ยฅ, โ‚น, โ‚ฝ, ยข, โ‚ช, โ‚ฟ, โ‚ฉ, โ‚ซ, โ‚ด, โ‚ฆ, โ‚ต, and many more
  • Examples: โ‚ช1,234.56 โ†’ 1234.56, โ‚ฟ0.001 โ†’ 0.001

API

parseNumber(value: string, options?: ParseOptions): number | null

Parses a string and returns a number or null if the input is invalid.

Parameters:

  • value (string): The string to parse
  • options (ParseOptions, optional): Configuration options

Returns:

  • number: The parsed number
  • null: If the input is invalid or empty

ParseOptions

interface ParseOptions {
  /** Strip any Unicode currency symbol (e.g. $, โ‚ฌ, โ‚ช, โ‚ฟ). Default: true */
  stripCurrency?: boolean;
  /** Allow Swiss-style apostrophe grouping (both ' and '). Default: true */
  allowApostrophe?: boolean;
  /** Allow scientific notation like 1.5e3. Default: false */
  allowScientific?: boolean;
}

Options Examples

// Default behavior
parseNumber(input, {
  stripCurrency: true,   // \p{Sc} removed by default
  allowApostrophe: true, // Swiss ' and ' grouping
  allowScientific: false // opt-in
});

// Disable currency stripping
parseNumber('$1,234.56', { stripCurrency: false }); // โ†’ null
parseNumber('1,234.56', { stripCurrency: false });  // โ†’ 1234.56

// Disable Swiss apostrophe format
parseNumber("1'234.56", { allowApostrophe: false }); // โ†’ null
parseNumber('1,234.56', { allowApostrophe: false }); // โ†’ 1234.56

// Enable scientific notation
parseNumber('1.5e3', { allowScientific: true });     // โ†’ 1500
parseNumber('1.5e-3', { allowScientific: true });     // โ†’ 0.0015

// Combine options
parseNumber('โ‚ช1'234.56', { 
  stripCurrency: true, 
  allowApostrophe: true, 
  allowScientific: false 
}); // โ†’ 1234.56

Validation Rules

The parser enforces strict validation rules:

  1. Thousands separators must be in groups of exactly 3 digits
  2. Decimal points can only appear once
  3. Signs (+/-) can only appear at the beginning
  4. Swiss apostrophes must follow proper 3-digit grouping
  5. Mixed separators are disambiguated by the last separator (decimal point)

Examples

// Valid inputs
parseNumber('1,234.56');        // โœ… 1234.56
parseNumber('1.234,56');        // โœ… 1234.56
parseNumber("1'234.56");        // โœ… 1234.56
parseNumber('1,000');           // โœ… 1000
parseNumber('1.000');           // โœ… 1000
parseNumber("1'000");           // โœ… 1000
parseNumber('-1,234.56');       // โœ… -1234.56
parseNumber('.5');              // โœ… 0.5
parseNumber(',5');              // โœ… 0.5

// Invalid inputs
parseNumber('1,23,456');        // โŒ null (invalid grouping)
parseNumber('1.23.456');        // โŒ null (invalid grouping)
parseNumber('1,234.56.78');     // โŒ null (multiple decimal points)
parseNumber('1-234.56');        // โŒ null (sign in middle)
parseNumber('1,234,56');        // โŒ null (ambiguous - could be 1,234,56 or 1,234.56)
parseNumber('');                // โŒ null (empty)
parseNumber('invalid');         // โŒ null (non-numeric)

Performance Benchmarks

Real-world Performance

Running performance benchmark...
Total time: 1170.28ms
Average time per parse: 0.0002ms
Parses per second: 4,443,387
Total operations: 5,200,000

Test Cases Covered

  • US format: 1,234.56
  • EU format: 1.234,56
  • Swiss format: 1'234.56
  • Scientific notation: 1.5e3
  • Currency symbols: โ‚ช1,234.56, 1,234.56$
  • Large numbers: 999,999,999.99
  • Small decimals: 0.001

Optimization Features

  • Pre-compiled regex patterns - No regex compilation overhead
  • Method extraction - Clean, maintainable code structure
  • Early returns - Minimal processing for invalid inputs
  • Unicode optimization - Efficient \p{Sc} class usage

Development

# Install dependencies
npm install

# Run tests
npm test

# Run tests in watch mode
npm run test:watch

# Build the library
npm run build

# Development mode with watch
npm run dev

Contributing

Contributions are welcome! Please open issues or pull requests on GitHub.

License

MIT ยฉ Norbert Lorincz