What is the JavaScript equivalent of C/PHP’s printf() or C#/Java’s String.Format()?
I’m looking for a JavaScript function that can format strings similar to how printf() works in C/PHP or String.Format() works in C#/Java. My primary need is to format numbers with thousand separators, but I’d also like a solution that can handle various formatting options including dates.
I’m aware that Microsoft’s Ajax library provides a String.Format() implementation, but I prefer a lightweight solution that doesn’t require the entire framework.
JavaScript doesn’t have a built-in printf() or String.Format() function like C/PHP or C#/Java, but there are several lightweight solutions available. The most common approaches include using the built-in Intl.NumberFormat API for number formatting with thousand separators, or creating custom format functions that support various formatting patterns.
Contents
- Built-in JavaScript Solutions
- Lightweight String Formatting Libraries
- Custom Format Function Implementation
- Number Formatting with Thousand Separators
- Date Formatting Options
- Comparison of Solutions
Built-in JavaScript Solutions
JavaScript provides several native APIs that can replace printf/String.Format functionality without requiring external libraries.
Intl.NumberFormat API
The Intl.NumberFormat object is the modern, built-in solution for number formatting with thousand separators and locale-specific formatting:
const number = 1234567.89;
// Basic number formatting with thousand separators
const formatted = new Intl.NumberFormat('en-US').format(number);
console.log(formatted); // "1,234,567.89"
// For different locales
const germanFormat = new Intl.NumberFormat('de-DE').format(number);
console.log(germanFormat); // "1.234.567,89"
// With currency formatting
const currencyFormat = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
}).format(number);
console.log(currencyFormat); // "$1,234,567.89"
Template Literals with Tag Functions
Modern JavaScript template literals with tag functions provide a flexible way to create formatted strings:
// Simple template literal
const name = "World";
const greeting = `Hello, ${name}!`;
// More complex formatting with custom tag function
function format(strings, ...values) {
return strings.reduce((result, string, i) => {
return result + string + (values[i] || '');
}, '');
}
const result = format`The price is $${1234.56} and the count is ${1000}`;
console.log(result); // "The price is $1234.56 and the count is 1000"
Lightweight String Formatting Libraries
Several lightweight libraries provide printf/String.Format functionality without the bulk of larger frameworks.
sprintf-js
A popular, lightweight implementation of sprintf functionality:
// Installation: npm install sprintf-js
const sprintf = require('sprintf-js').sprintf;
// Basic string formatting
const formatted = sprintf("Hello %s, you have %d messages", "Alice", 5);
console.log(formatted); // "Hello Alice, you have 5 messages"
// Number formatting with thousand separators
const number = 1234567;
const formattedNum = sprintf("%'d", number); // Using ' for thousand separator
console.log(formattedNum); // "1,234,567"
string-format
Another lightweight option with simple syntax:
// Installation: npm install string-format
const format = require('string-format');
// Basic usage
const result = format("Hello {0}, you have {1} messages", "Alice", 5);
console.log(result); // "Hello Alice, you have 5 messages"
// Named parameters
const namedResult = format("Hello {name}, you have {count} messages", {
name: "Alice",
count: 5
});
console.log(namedResult); // "Hello Alice, you have 5 messages"
util.format
Node.js provides a built-in util.format method similar to printf:
const util = require('util');
const formatted = util.format("Hello %s, you have %d messages", "Alice", 5);
console.log(formatted); // "Hello Alice, you have 5 messages"
Custom Format Function Implementation
You can create your own lightweight format function that covers printf-like functionality:
function printf(format, ...args) {
return format.replace(/%([%sdf])/g, function(match, type) {
const value = args.shift();
switch(type) {
case '%': return '%';
case 's': return String(value);
case 'd': return Math.floor(value);
case 'f': return parseFloat(value).toFixed(2);
default: return match;
}
});
}
// Usage examples
const result1 = printf("Hello %s, you have %d messages", "Alice", 5);
const result2 = printf("The price is $%f", 1234.567);
console.log(result1); // "Hello Alice, you have 5 messages"
console.log(result2); // "The price is $1234.57"
For more comprehensive formatting, here’s an enhanced version:
function formatString(format, ...args) {
return format.replace(/%(%)|(%(\d+)\$)?([-+ 0#])*(\d+)?(?:\.(\d+))?([diufFeEgGcsb])|{(\d+)(?::([^}]+))?}/g, function(match, literal, positional, pos, flags, width, precision, type, index, formatSpec) {
let value;
// Handle printf-style positional arguments
if (positional) {
value = args[parseInt(pos) - 1];
}
// Handle template literal style {index}
else if (index !== undefined) {
value = args[parseInt(index)];
}
// Handle printf-style sequential arguments
else if (!literal) {
value = args.shift();
}
if (value === undefined) return match;
// Format based on type
switch(type) {
case '%': return '%';
case 's': return String(value);
case 'd': case 'i': return Math.floor(value).toLocaleString();
case 'f': case 'F': return parseFloat(value).toFixed(precision || 2).toLocaleString();
case 'e': case 'E': return parseFloat(value).toExponential(precision || 2);
case 'g': case 'G': return parseFloat(value).toPrecision(precision || 6);
case 'c': return value;
case 'b': return parseInt(value).toString(2);
default: return String(value);
}
});
}
// Usage examples
console.log(formatString("Hello %s, balance: $%d", "Alice", 1234567));
console.log(formatString("Precision: %0.2f", 3.14159));
console.log(formatString("Scientific: %e", 1000000));
console.log(formatString("Template: {0} has {1:,d} points", "Bob", 9876543));
Number Formatting with Thousand Separators
For your primary need of formatting numbers with thousand separators, here are several approaches:
Using Intl.NumberFormat (Recommended)
function formatNumber(number, locale = 'en-US') {
return new Intl.NumberFormat(locale).format(number);
}
// Usage
console.log(formatNumber(1234567)); // "1,234,567"
console.log(formatNumber(1234567.89, 'de-DE')); // "1.234.567,89"
console.log(formatNumber(1234567, 'fr-FR')); // "1 234 567"
Using Custom Number Formatting
function formatNumberWithSeparators(number, separator = ',') {
return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, separator);
}
// Usage
console.log(formatNumberWithSeparators(1234567)); // "1,234,567"
console.log(formatNumberWithSeparators(1234567, '.')); // "1.234.567"
Combining with Other Number Formatting
function formatCurrency(amount, currency = 'USD', locale = 'en-US') {
return new Intl.NumberFormat(locale, {
style: 'currency',
currency: currency,
minimumFractionDigits: 2,
maximumFractionDigits: 2
}).format(amount);
}
function formatPercent(value, decimals = 2, locale = 'en-US') {
return new Intl.NumberFormat(locale, {
style: 'percent',
minimumFractionDigits: decimals,
maximumFractionDigits: decimals
}).format(value / 100);
}
// Usage
console.log(formatCurrency(1234567.89)); // "$1,234,567.89"
console.log(formatPercent(0.1567)); // "15.67%"
Date Formatting Options
JavaScript also provides robust date formatting through the Intl.DateTimeFormat API:
function formatDate(date, locale = 'en-US', options = {}) {
const defaultOptions = {
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
};
return new Intl.DateTimeFormat(locale, { ...defaultOptions, ...options }).format(date);
}
// Usage examples
const now = new Date();
console.log(formatDate(now));
// "December 31, 2024 at 11:59:59 PM"
console.log(formatDate(now, 'de-DE', {
year: 'numeric',
month: 'short',
day: 'numeric'
}));
// "31. Dez. 2024"
console.log(formatDate(now, 'ja-JP', {
era: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
weekday: 'long'
}));
// "2024年12月31日 火曜日"
For printf-style date formatting, you can extend the custom format function:
function formatDateTime(format, date = new Date(), ...args) {
const pad = (num, width = 2) => num.toString().padStart(width, '0');
const dateObj = new Date(date);
// Date format specifiers
const formatMap = {
'%Y': dateObj.getFullYear(),
'%y': dateObj.getFullYear() % 100,
'%m': pad(dateObj.getMonth() + 1),
'%d': pad(dateObj.getDate()),
'%H': pad(dateObj.getHours()),
'%M': pad(dateObj.getMinutes()),
'%S': pad(dateObj.getSeconds()),
'%A': dateObj.toLocaleDateString('en-US', { weekday: 'long' }),
'%B': dateObj.toLocaleDateString('en-US', { month: 'long' }),
'%b': dateObj.toLocaleDateString('en-US', { month: 'short' }),
};
// Replace format specifiers
let result = format;
for (const [spec, value] of Object.entries(formatMap)) {
result = result.replace(new RegExp(spec.replace('%', '\\%'), 'g'), value);
}
// Handle remaining printf-style formatting
return result.replace(/%(%)|(%(\d+)\$)?([-+ 0#])*(\d+)?(?:\.(\d+))?([diufFeEgGcsb])/g, function(match, literal, positional, pos, flags, width, precision, type) {
if (literal) return '%';
return args.shift() || '';
});
}
// Usage
console.log(formatDateTime("Today is %A, %B %d, %Y"));
console.log(formatDateTime("Time: %H:%M:%S", new Date(), "additional", "args"));
Comparison of Solutions
| Solution | Pros | Cons | Best For |
|---|---|---|---|
Intl.NumberFormat |
Built-in, locale-aware, no dependencies | Limited to number formatting | Modern applications needing international number formatting |
sprintf-js |
Full printf compatibility, lightweight | Requires external dependency | C/PHP developers wanting familiar syntax |
| Custom format function | Complete control, no dependencies | Requires maintenance | Projects needing specific, custom formatting |
| Template literals | Native JavaScript, readable | Limited formatting capabilities | Simple string interpolation |
util.format |
Built-in (Node.js), familiar syntax | Node.js only only | Server-side JavaScript applications |
For your specific needs, I recommend starting with Intl.NumberFormat for number formatting with thousand separators, as it’s built-in, locale-aware, and requires no external dependencies. For more comprehensive string formatting needs, sprintf-js provides excellent printf compatibility while remaining lightweight.
Conclusion
JavaScript provides several excellent alternatives to C/PHP’s printf() and C#/Java’s String.Format(), ranging from built-in APIs to lightweight libraries. For your primary need of formatting numbers with thousand separators, the Intl.NumberFormat API is the recommended modern solution. For more comprehensive string formatting, libraries like sprintf-js offer printf-style functionality without requiring large frameworks. The custom implementation approach gives you complete control over the formatting behavior while maintaining minimal footprint.
Key Recommendations:
- Use
Intl.NumberFormatfor number formatting with thousand separators and locale support - Consider
sprintf-jsfor comprehensive printf-style string formatting - Implement custom format functions for project-specific formatting needs
- Leverage template literals for simple string interpolation tasks
- Combine
Intl.NumberFormatwithIntl.DateTimeFormatfor consistent international formatting
These solutions provide the functionality you need while maintaining the lightweight approach you prefer, eliminating the requirement for larger frameworks like Microsoft’s Ajax library.