Lightweight date formatting and parsing library designed as a modern replacement for moment.js
npx @tessl/cli install tessl/npm-fecha@4.2.0Fecha is a lightweight TypeScript date formatting and parsing library (~2KB minified and gzipped) designed as a modern replacement for the parsing and formatting functionality of moment.js. It provides comprehensive date formatting and parsing capabilities with support for custom format tokens, named masks, and internationalization (i18n).
npm install fechaimport { format, parse, setGlobalDateI18n, setGlobalDateMasks, defaultI18n } from "fecha";For CommonJS:
const { format, parse, setGlobalDateI18n, setGlobalDateMasks, defaultI18n } = require("fecha");Default import (contains all functions):
import fecha from "fecha";
// fecha.format, fecha.parse, fecha.defaultI18n, etc.import { format, parse } from "fecha";
// Format dates
const formatted = format(new Date(2023, 10, 20), 'YYYY-MM-DD');
// Result: '2023-11-20'
// Parse date strings
const parsed = parse('2023-11-20', 'YYYY-MM-DD');
// Result: Date object for November 20, 2023
// Use named masks
const dateStr = format(new Date(), 'mediumDate');
// Result: 'Nov 20, 2023'
// Custom format with tokens
const custom = format(new Date(2023, 10, 20, 15, 30), 'dddd MMMM Do, YYYY [at] HH:mm');
// Result: 'Monday November 20th, 2023 at 15:30'Fecha is built around several key architectural components that work together to provide robust date formatting and parsing:
Token System: Uses regular expressions to identify and process format tokens (YYYY, MM, DD, etc.) in format strings. The core token regex matches various patterns and replaces them with corresponding values or parsing logic.
Format Pipeline: Formatting uses a formatFlags object that maps each token to a transformation function. These functions receive a Date object and i18n settings, returning the appropriate string representation.
Parse Pipeline: Parsing reverses this process using parseFlags that map tokens to regex patterns and parsing functions. The system builds a composite regex from the format string and extracts values to construct a Date object.
Internationalization Layer: Global i18n settings (globalI18n) can be overridden per-call. The system merges settings using the assign utility, allowing flexible localization without affecting global state.
Mask Registry: Named format shortcuts are stored in globalMasks and resolved before token processing. This allows reusable format definitions like 'shortDate' and 'isoDateTime'.
Validation Engine: Date parsing includes comprehensive validation that checks field ranges, validates constructed dates against input fields, and handles timezone offset calculations.
Convert Date objects or timestamps into formatted strings using custom format tokens or predefined masks.
/**
* Format a date into a string using format tokens or named masks
* @param dateObj - Date object or timestamp to format
* @param mask - Format string (defaults to global default), can be custom format or named mask
* @param i18n - Optional internationalization settings override
* @returns Formatted date string
* @throws Error for invalid Date objects
*/
function format(
dateObj: Date,
mask?: string,
i18n?: I18nSettingsOptional
): string;Usage Examples:
import { format } from "fecha";
// Basic formatting
format(new Date(2023, 10, 20), 'YYYY-MM-DD'); // '2023-11-20'
format(new Date(2023, 5, 15, 14, 30, 25), 'YYYY-MM-DD HH:mm:ss'); // '2023-06-15 14:30:25'
// Named masks
format(new Date(2023, 10, 20), 'shortDate'); // '11/20/23'
format(new Date(2023, 10, 20), 'mediumDate'); // 'Nov 20, 2023'
format(new Date(2023, 10, 20), 'isoDate'); // '2023-11-20'
// Custom format with literals
format(new Date(2023, 10, 20, 15, 30), '[Today is] dddd, MMMM Do'); // 'Today is Monday, November 20th'
// Timestamps work too
format(1700482800000, 'YYYY-MM-DD'); // '2023-11-20'Parse date strings into JavaScript Date objects using format patterns with validation.
/**
* Parse a date string into a JavaScript Date object
* @param dateStr - Date string to parse
* @param format - Parse format (required), can be custom format or named mask
* @param i18n - Optional internationalization settings override
* @returns Date object or null if parsing fails or date is invalid
* @throws Error for invalid format strings or missing format parameter
*/
function parse(
dateStr: string,
format: string,
i18n?: I18nSettingsOptional
): Date | null;Usage Examples:
import { parse } from "fecha";
// Basic parsing
parse('2023-11-20', 'YYYY-MM-DD'); // Date object for November 20, 2023
parse('15:30:25', 'HH:mm:ss'); // Date object for today at 15:30:25
// Named masks
parse('11/20/23', 'shortDate'); // Date object for November 20, 2023
parse('Nov 20, 2023', 'mediumDate'); // Date object for November 20, 2023
// Complex formats
parse('Monday November 20th, 2023', 'dddd MMMM Do, YYYY'); // Date object
parse('3:30 PM', 'h:mm A'); // Date object for today at 15:30
// Invalid dates return null
parse('2023-13-45', 'YYYY-MM-DD'); // null (invalid month/day)
parse('invalid', 'YYYY-MM-DD'); // null (doesn't match format)Configure global internationalization settings or provide per-call overrides for different languages and locales.
/**
* Set global internationalization settings
* @param i18n - Partial I18N settings to merge with current global settings
* @returns Updated global I18N settings
*/
function setGlobalDateI18n(i18n: I18nSettingsOptional): I18nSettings;
/**
* Default internationalization settings with English names
*/
const defaultI18n: I18nSettings;Usage Examples:
import { setGlobalDateI18n, format, parse } from "fecha";
// Set Spanish locale globally
setGlobalDateI18n({
monthNames: [
'enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio',
'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'
],
dayNames: [
'domingo', 'lunes', 'martes', 'miércoles',
'jueves', 'viernes', 'sábado'
]
});
// Now formatting uses Spanish names
format(new Date(2023, 10, 20), 'dddd, MMMM DD'); // 'lunes, noviembre 20'
// Per-call override (doesn't affect global settings)
const frenchFormat = format(new Date(2023, 10, 20), 'MMMM', {
monthNames: [
'janvier', 'février', 'mars', 'avril', 'mai', 'juin',
'juillet', 'août', 'septembre', 'octobre', 'novembre', 'décembre'
]
}); // 'novembre'
// Parsing with custom i18n
parse('20 de noviembre de 2023', 'DD de MMMM de YYYY', {
monthNames: [
'enero', 'febrero', 'marzo', 'abril', 'mayo', 'junio',
'julio', 'agosto', 'septiembre', 'octubre', 'noviembre', 'diciembre'
]
}); // Date object for November 20, 2023Define and use custom named format masks for reusable date formats across your application.
/**
* Set global date format masks/shortcuts
* @param masks - Object with mask names as keys and format strings as values
* @returns Updated global masks object
*/
function setGlobalDateMasks(masks: { [key: string]: string }): { [key: string]: string };Usage Examples:
import { setGlobalDateMasks, format } from "fecha";
// Define custom masks
setGlobalDateMasks({
apiDate: 'YYYY-MM-DDTHH:mm:ssZ',
logFormat: 'YYYY-MM-DD HH:mm:ss.SSS',
displayDate: 'MMM DD, YYYY [at] h:mm A'
});
// Use custom masks
const now = new Date();
format(now, 'apiDate'); // '2023-11-20T15:30:25Z'
format(now, 'logFormat'); // '2023-11-20 15:30:25.123'
format(now, 'displayDate'); // 'Nov 20, 2023 at 3:30 PM'
// Built-in masks are still available
format(now, 'shortDate'); // '11/20/23'
format(now, 'isoDateTime'); // '2023-11-20T15:30:25Z'Helper functions for object manipulation and type safety.
/**
* Object assignment utility with type safety (similar to Object.assign)
*/
function assign<A>(a: A): A;
function assign<A, B>(a: A, b: B): A & B;
function assign<A, B, C>(a: A, b: B, c: C): A & B & C;
function assign<A, B, C, D>(a: A, b: B, c: C, d: D): A & B & C & D;Comprehensive list of format tokens supported for both formatting and parsing:
Use square brackets to include literal text in format strings:
Pre-defined format masks for common date formats:
/**
* Complete internationalization settings interface
*/
interface I18nSettings {
/** AM/PM labels */
amPm: [string, string];
/** Full day names array (Sunday through Saturday) */
dayNames: Days;
/** Short day names array (3 characters each) */
dayNamesShort: Days;
/** Full month names array (January through December) */
monthNames: Months;
/** Short month names array (3 characters each) */
monthNamesShort: Months;
/** Function to generate ordinal day suffixes (1st, 2nd, 3rd, etc.) */
DoFn(dayOfMonth: number): string;
}
/**
* Partial internationalization settings for optional overrides
*/
type I18nSettingsOptional = Partial<I18nSettings>;
/**
* Tuple type for 7 day names (Sunday through Saturday)
*/
type Days = [string, string, string, string, string, string, string];
/**
* Tuple type for 12 month names (January through December)
*/
type Months = [
string, string, string, string, string, string,
string, string, string, string, string, string
];Error for invalid Date objects or timestampsError for invalid format strings or missing format parameternull for strings that don't match the format or represent invalid datesError Examples:
import { format, parse } from "fecha";
// Format errors
format(new Date('invalid')); // Throws Error: "Invalid Date pass to format"
format(null); // Throws Error
// Parse errors
parse('2023-11-20'); // Throws Error: "Invalid format in fecha parse" (missing format)
parse('2023-11-20', null); // Throws Error: "Invalid format in fecha parse"
// Parse returns null for invalid data
parse('2023-13-45', 'YYYY-MM-DD'); // null (invalid month)
parse('not-a-date', 'YYYY-MM-DD'); // null (doesn't match format)
parse('2023-02-29', 'YYYY-MM-DD'); // null (not a leap year)