chronal
v0.0.21
Published
A tiny and fast date utility library for modern JavaScript runtimes.
Maintainers
Readme
Chronal
A tiny, fast, and modern date utility library for JavaScript/TypeScript with zero dependencies.
Features
- 🪶 Lightweight - Zero dependencies, minimal bundle size
- 🌍 i18n Support - Locale-aware formatting with
IntlAPI - ⏰ UTC First - All operations work in UTC by default, avoiding timezone pitfalls
- 🎯 Two APIs - Choose between tree-shakeable functions or chainable object API
- 📦 Tree-shakeable - Import only what you need
- 🦕 Deno Native - Built for Deno, works everywhere
- ✅ Fully Tested - Comprehensive test coverage
Table of Contents
- Features
- Installation
- Quick Start
- Configuration
- API Reference
- Performance
- Why Chronal?
- Design Principles
- Browser Support
- Contributing
- License
Installation
Deno
// Functional API (tree-shakeable)
import { addTime, formatDate, subtractTime } from "jsr:@chronal/core";
// Chainable API
import { chronal } from "jsr:@chronal/core/chainable";Node.js / npm
npm install chronal// Functional API (tree-shakeable)
import { addTime, formatDate, subtractTime } from "chronal";
// Chainable API
import { chronal } from "chronal/chainable";Bundle Size
- Functional API (tree-shakeable): ~2.3 KB gzipped for typical imports (5 functions)
- Chainable API: ~4.8 KB gzipped (includes all functionality)
Choose the functional API for libraries and performance-critical code, or the chainable API for better developer experience in applications.
Quick Start
Chronal offers two ways to work with dates:
1. Functional API (Tree-shakeable)
Perfect for minimal bundle size (~2.3 KB gzipped) - import only what you need:
import {
addTime,
endOf,
formatDate,
fromNow,
isToday,
parseDate,
startOf,
subtract,
} from "chronal";
const date = new Date("2024-06-15T14:35:22Z");
// Format dates
formatDate(date, "YYYY-MM-DD"); // '2024-06-15'
formatDate(date, "YYYY-MM-DD HH:mm:ss"); // '2024-06-15 14:35:22'
formatDate(date, "DD/MM/YYYY [at] HH:mm"); // '15/06/2024 at 14:35'
// Parse dates
parseDate("15/06/2024", "DD/MM/YYYY"); // Date object for June 15, 2024
// Add/subtract time
addTime(date, { days: 5, hours: 2 }); // 2024-06-20T16:35:22Z
subtract(date, { months: 1, days: 10 }); // 2024-05-05T14:35:22Z
// Start/End of period
startOf(date, "month"); // 2024-06-01T00:00:00.000Z
endOf(date, "day"); // 2024-06-15T23:59:59.999Z
// Relative time
fromNow(new Date(Date.now() - 300000)); // "5 minutes ago"
// Date checks
isToday(new Date()); // true
// Generate date ranges
datesUntil(new Date("2024-01-01"), new Date("2024-01-05"));
// [2024-01-01, 2024-01-02, 2024-01-03, 2024-01-04, 2024-01-05]2. Chainable API
Perfect for developer experience with convenient method chaining (~4.8 KB gzipped):
import { chronal } from "chronal/chainable";
// Create and chain operations
const date = chronal("2024-06-15T14:35:22Z")
.add({ months: 1, days: 5 })
.startOf("month")
.format("YYYY-MM-DD");
console.log(date); // "2024-07-01"
// Create with timezone - all operations use this timezone by default
const spDate = chronal("2024-06-15T14:30:00", { tz: "America/Sao_Paulo" });
spDate.format("YYYY-MM-DD HH:mm"); // Uses São Paulo time
spDate.startOf("day"); // Start of day in São Paulo
spDate.add({ days: 1 }); // Timezone is preserved
// All methods available
const result = chronal("2024-01-15")
.add({ days: 10 })
.subtract({ hours: 2 })
.format("MMMM DD, YYYY"); // "January 25, 2024"
// Query methods
chronal("2024-06-15").isLeapYear(); // true
chronal().isToday(); // true
chronal("2024-01-01").fromNow(); // "1 year ago"
// Get values
chronal("2024-06-15").get("month"); // 5 (0-indexed)
chronal("2024-06-15").quarter(); // 2
chronal("2024-06-15").daysInMonth(); // 30
// Generate date ranges
chronal("2024-01-01")
.until(new Date("2024-01-31"), { weeks: 1 })
.map((c) => c.format("YYYY-MM-DD"));
// ["2024-01-01", "2024-01-08", "2024-01-15", "2024-01-22", "2024-01-29"]Choose what fits your needs:
- Use functional API for maximum tree-shaking (smaller bundles)
- Use chainable API for better DX and readable code
- Mix both styles in the same project!
Configuration
setChronalConfig(config)
Set the default configuration for all date operations.
Parameters:
config(object) - Configuration object with optional properties:locale(string) - The locale code (e.g., 'en-US', 'pt-BR', 'fr-FR')timezone(string) - The default IANA timezone (e.g., 'UTC', 'America/Sao_Paulo')
Example:
import { formatDate, months, setChronalConfig, chronal } from "chronal";
// Default is 'en-US' and 'UTC'
formatDate(new Date("2024-06-15"), "MMMM"); // 'June'
// Change default locale
setChronalConfig({ locale: "pt-BR" });
formatDate(new Date("2024-06-15"), "MMMM"); // 'junho'
months(); // ['janeiro', 'fevereiro', 'março', ...]
// Change default timezone
setChronalConfig({ timezone: "America/Sao_Paulo" });
// You can still override per call
formatDate(new Date("2024-06-15"), "MMMM", { locale: "fr-FR" }); // 'juin'Per-Instance Timezone (Chainable API)
When using the chainable API, you can set a timezone for a specific instance. This timezone will be used for all operations on that instance:
import { chronal } from "chronal";
// Create instance with timezone
const spDate = chronal("2024-06-15T14:30:00", { tz: "America/Sao_Paulo" });
// All operations use the instance timezone
spDate.format("YYYY-MM-DD HH:mm"); // Uses São Paulo time (UTC-3)
spDate.startOf("day"); // Start of day in São Paulo
spDate.endOf("month"); // End of month in São Paulo
// Timezone is preserved across operations
const nextDay = spDate.add({ days: 1 });
nextDay.timezone; // "America/Sao_Paulo"
// Override timezone for specific operation
spDate.format("HH:mm", { tz: "UTC" }); // Use UTC instead
// Generated dates preserve timezone
const dates = spDate.until(new Date("2024-06-20"));
dates[0].timezone; // "America/Sao_Paulo"Benefits:
- ✅ Set timezone once, use everywhere in the chain
- ✅ Prevents accidental timezone mixing
- ✅ Clean API - no need to pass timezone to every method
- ✅ Can still override per method when needed
API Reference
Chainable Object API
The chronal object provides a chainable API for convenient date manipulation.
chronal(date?, options?)
Creates a Chronal instance with chainable methods.
Parameters:
date(Date | string | number, optional) - Initial date (defaults to current date)options(object, optional) - Configuration options:tz(string) - IANA timezone for this instance (e.g., 'America/Sao_Paulo')
Returns: Chronal instance with optional timezone
Examples:
// Create with current time
const now = chronal();
// Create from string
const date = chronal("2024-06-15");
// Create with timezone - all operations will use this timezone
const spDate = chronal("2024-06-15", { tz: "America/Sao_Paulo" });
spDate.format("YYYY-MM-DD HH:mm"); // Uses São Paulo time
spDate.startOf("day").timezone; // "America/Sao_Paulo" (preserved)API Reference:
All chainable methods correspond to functional API functions:
| Chainable Method | Functional API | Description |
| ------------------------- | ------------------------------------- | ------------------------ |
| .add(options) | addTime(date, options) | Add time units |
| .subtract(options) | subtract(date, options) | Subtract time units |
| .startOf(unit) | startOf(date, unit) | Start of time unit |
| .endOf(unit) | endOf(date, unit) | End of time unit |
| .set(options) | setUnit(date, options) | Set specific units |
| .clamp(min, max) | clampDate(date, min, max) | Clamp between dates |
| .format(pattern, opts?) | formatDate(date, pattern, opts?) | Format date |
| .fromNow(locale?) | fromNow(date, locale?) | Relative time from now |
| .toNow(locale?) | toNow(date, locale?) | Relative time to now |
| .diff(date, unit) | dateDiff(dateLeft, dateRight, unit) | Difference between dates |
| .isAfter(date) | isAfter(date1, date2) | Is after date |
| .isBefore(date) | isBefore(date1, date2) | Is before date |
| .isBetween(start, end) | isBetween(date, start, end) | Is between dates |
| .isEqual(date) | isEqual(date1, date2) | Is equal to date |
| .isSame(date, unit) | isSame(date1, date2, unit) | Is same time unit |
| .isToday() | isToday(date) | Is today |
| .isTomorrow() | isTomorrow(date) | Is tomorrow |
| .isYesterday() | isYesterday(date) | Is yesterday |
| .isLeapYear() | isLeapYear(date) | Is leap year |
| .isValid() | isValidDate(date) | Is valid date |
| .get(unit) | getUnit(date, unit) | Get specific unit value |
| .quarter() | getQuarter(date) | Get quarter (1-4) |
| .daysInMonth() | daysInMonth(date) | Days in month |
| .week() | weekOfYear(date) | Week of year |
| .until(end, step?) | datesUntil(start, end, step?) | Generate date array |
Example:
import { chronal } from "chronal";
// Create instance
const date = chronal("2024-06-15");
// Chain operations
const result = chronal("2024-01-15")
.add({ months: 6, days: 10 })
.startOf("month")
.add({ days: 5 })
.format("YYYY-MM-DD");
console.log(result); // "2024-07-06"
// Query methods
chronal("2024-06-15").isLeapYear(); // true
chronal().isToday(); // true
chronal("2024-06-15").diff(chronal("2024-07-15"), "days"); // -30
// All methods return new instances (immutable)
const original = chronal("2024-01-01");
const modified = original.add({ months: 1 });
console.log(original.format("MM")); // "01"
console.log(modified.format("MM")); // "02"Formatting
formatDate(date, formatString, options?)
Formats a date into a string using the specified format pattern.
Parameters:
date(Date) - The date to formatformatString(string) - Format pattern with tokensoptions(object, optional)locale(string) - Locale for internationalization (default: 'en-US')tz(string) - Timezone (default: 'UTC')
Format Tokens:
| Token | Output | Description |
| ------ | --------- | ----------------------- |
| YYYY | 2024 | 4-digit year |
| YY | 24 | 2-digit year |
| MMMM | June | Full month name |
| MMM | Jun | Short month name |
| MM | 06 | 2-digit month |
| M | 6 | Month number |
| DD | 05 | 2-digit day |
| D | 5 | Day of month |
| dddd | Saturday | Full weekday name |
| ddd | Sat | Short weekday name |
| HH | 14 | 2-digit hour (24h) |
| H | 14 | Hour (24h) |
| mm | 35 | 2-digit minute |
| m | 35 | Minute |
| ss | 22 | 2-digit second |
| s | 22 | Second |
Literals: Use square brackets to escape literals: [at] → "at"
Examples:
const date = new Date("2024-06-15T14:35:22Z"); // This is a Saturday
formatDate(date, "YYYY-MM-DD"); // '2024-06-15'
formatDate(date, "DD/MM/YYYY HH:mm"); // '15/06/2024 14:35'
formatDate(date, "MMMM D, YYYY"); // 'June 15, 2024'
formatDate(date, "dddd, MMMM D, YYYY"); // 'Saturday, June 15, 2024'
formatDate(date, "ddd, MMM D"); // 'Sat, Jun 15'
formatDate(date, "YYYY-MM-DD [at] HH:mm"); // '2024-06-15 at 14:35'
// With locale
formatDate(date, "dddd, MMMM D, YYYY", { locale: "pt-BR" }); // 'sábado, junho 15, 2024'
formatDate(date, "ddd, D [de] MMM", { locale: "es-ES" }); // 'sáb, 15 de jun'Parsing
parseDate(dateString, format?)
Parses a date string into a Date object using an optional format pattern.
Parameters:
dateString(string) - The date string to parseformat(string, optional) - Format pattern (e.g., "YYYY-MM-DD", "DD/MM/YYYY")options(object, optional) - Parsing optionstz(string) - IANA timezone (e.g., 'America/Sao_Paulo')
Returns: Date object
Timezone Behavior:
When parsing date strings, parseDate follows these rules:
- Explicit timezone (e.g.,
Zor+03:00) - Always respected, ignoresconfig.timezone - No timezone - Uses
config.timezoneor thetzoption to interpret the string as local time in that timezone
// With explicit UTC marker (Z) - always UTC
parseDate("2026-01-12T02:59:59.999Z"); // UTC time, ignores config
// Without timezone - uses config.timezone
setChronalConfig({ timezone: "America/Sao_Paulo" });
parseDate("2026-01-12T02:59:59.999"); // Interpreted as São Paulo time
parseDate("2026-01-12"); // Midnight in São PauloSupported Tokens:
YYYY- 4-digit yearMM- 2-digit monthDD- 2-digit dayHH- 2-digit hour (24h)mm- 2-digit minutess- 2-digit second
Examples:
// Without format (uses native Date parser)
parseDate("2024-06-15"); // Date object
// With custom format
parseDate("15/06/2024", "DD/MM/YYYY");
parseDate("2024-06-15 14:30:00", "YYYY-MM-DD HH:mm:ss");
parseDate("06/15/2024", "MM/DD/YYYY");
// With timezone
parseDate("2024-06-15", { tz: "America/Sao_Paulo" }); // Parse as São Paulo timeManipulation
addTime(date, options)
Adds specified time units to a date.
Parameters:
date(Date) - The original dateoptions(object) - Time units to addyears(number)months(number)weeks(number)days(number)hours(number)minutes(number)seconds(number)milliseconds(number)
Returns: New Date object
Examples:
const date = new Date("2024-01-31T12:00:00Z");
addTime(date, { days: 5 }); // 2024-02-05T12:00:00.000Z
addTime(date, { months: 1 }); // 2024-02-29T12:00:00.000Z (handles leap year)
addTime(date, { years: 1, months: 2, days: 3 }); // 2025-04-03T12:00:00.000Zsubtract(date, options)
Subtracts specified time units from a date.
Parameters: Same as addTime()
Examples:
const date = new Date("2024-03-31T12:00:00Z");
subtract(date, { days: 5 }); // 2024-03-26T12:00:00.000Z
subtract(date, { months: 1 }); // 2024-02-29T12:00:00.000Z (handles month overflow)getUnit(date, unit)
Extracts a specific unit from a date.
Parameters:
date(Date) - The date to extract fromunit('year' | 'month' | 'date' | 'day' | 'hour' | 'minute' | 'second')- Note:
'week'is not supported 'date'returns the day of the month (1-31)'day'returns the day of the week (0-6, where 0 is Sunday)
- Note:
Returns: Number
Examples:
const date = new Date("2024-06-15T14:35:22.500Z"); // This is a Saturday
getUnit(date, "year"); // 2024
getUnit(date, "month"); // 5 (0-indexed, June)
getUnit(date, "date"); // 15 (day of month)
getUnit(date, "day"); // 6 (day of week: Saturday)
getUnit(date, "hour"); // 14setUnit(date, unit, value)
Sets a specific unit of a date to a new value, returning a new Date object.
Parameters:
date(Date) - The date to modifyunit('year' | 'month' | 'day' | 'hour' | 'minute' | 'second' | 'millisecond')value(number) - The new value
Returns: New Date object
Examples:
const date = new Date("2024-06-15T14:35:22Z");
setUnit(date, "year", 2025); // 2025-06-15T14:35:22Z
setUnit(date, "month", 0); // 2024-01-15T14:35:22Z (January)
setUnit(date, "day", 20); // 2024-06-20T14:35:22ZStart & End of Period
startOf(date, unit)
Returns the start of the specified time unit.
Parameters:
date(Date) - The original dateunit('year' | 'month' | 'day' | 'hour' | 'minute' | 'second')
Examples:
const date = new Date("2024-06-15T14:35:22.500Z");
startOf(date, "year"); // 2024-01-01T00:00:00.000Z
startOf(date, "month"); // 2024-06-01T00:00:00.000Z
startOf(date, "day"); // 2024-06-15T00:00:00.000ZendOf(date, unit)
Returns the end (last millisecond) of the specified time unit.
Parameters: Same as startOf()
Examples:
const date = new Date("2024-06-15T14:35:22.500Z");
endOf(date, "year"); // 2024-12-31T23:59:59.999Z
endOf(date, "month"); // 2024-06-30T23:59:59.999Z
endOf(date, "day"); // 2024-06-15T23:59:59.999ZComparison
isAfter(dateLeft, dateRight)
Checks if the first date is after the second date.
const date1 = new Date("2024-01-20T12:00:00Z");
const date2 = new Date("2024-01-15T12:00:00Z");
isAfter(date1, date2); // trueisBefore(dateLeft, dateRight)
Checks if the first date is before the second date.
isBefore(date2, date1); // trueisEqual(dateLeft, dateRight)
Checks if two dates are equal (same exact millisecond).
const date1 = new Date("2024-01-15T12:00:00.000Z");
const date2 = new Date("2024-01-15T12:00:00.000Z");
isEqual(date1, date2); // trueisSame(dateLeft, dateRight, unit)
Checks if two dates are in the same time unit.
Parameters:
dateLeft(Date)dateRight(Date)unit('year' | 'month' | 'week' | 'day' | 'hour' | 'minute' | 'second')
const date1 = new Date("2024-06-15T14:30:00Z");
const date2 = new Date("2024-06-15T18:45:00Z");
isSame(date1, date2, "day"); // true (same day)
isSame(date1, date2, "hour"); // false (different hours)isBetween(date, start, end, inclusivity?)
Checks if a date is between two other dates.
Parameters:
date(Date) - The date to checkstart(Date) - Start of rangeend(Date) - End of rangeinclusivity('[]' | '()' | '[)' | '(]', optional) - Default: '[]'[]- inclusive on both ends()- exclusive on both ends[)- inclusive start, exclusive end(]- exclusive start, inclusive end
const date = new Date("2024-06-15");
const start = new Date("2024-06-01");
const end = new Date("2024-06-30");
isBetween(date, start, end); // true
isBetween(date, start, end, "()"); // true
isBetween(start, start, end, "()"); // false (exclusive)isToday(date)
Checks if a date is today (in UTC).
isToday(new Date()); // true
isToday(new Date("2024-01-01")); // falseisTomorrow(date)
Checks if a date is tomorrow (in UTC).
const tomorrow = new Date(Date.now() + 86400000);
isTomorrow(tomorrow); // trueisYesterday(date)
Checks if a date is yesterday (in UTC).
const yesterday = new Date(Date.now() - 86400000);
isYesterday(yesterday); // trueisValidDate(date)
Checks if a Date object is valid (not Invalid Date).
isValidDate(new Date("2024-06-15")); // true
isValidDate(new Date("invalid")); // false
isValidDate(new Date(NaN)); // falseRelative Time
fromNow(date)
Returns how long ago the date was from now, or how long until it in the future.
Returns: String ("5 minutes ago", "in 2 hours", "just now")
const fiveMinutesAgo = new Date(Date.now() - 300000);
fromNow(fiveMinutesAgo); // "5 minutes ago"
const inTwoHours = new Date(Date.now() + 7200000);
fromNow(inTwoHours); // "in 2 hours"toNow(date)
Returns the time from now to the date (inverse of fromNow).
const inFiveMinutes = new Date(Date.now() + 300000);
toNow(inFiveMinutes); // "in 5 minutes"
const twoHoursAgo = new Date(Date.now() - 7200000);
toNow(twoHoursAgo); // "2 hours ago"Utilities
maxDate(...dates)
Returns the latest date from the given dates.
const date1 = new Date("2024-01-15T12:00:00Z");
const date2 = new Date("2024-01-20T12:00:00Z");
const date3 = new Date("2024-01-10T12:00:00Z");
maxDate(date1, date2, date3); // 2024-01-20T12:00:00.000ZminDate(...dates)
Returns the earliest date from the given dates.
minDate(date1, date2, date3); // 2024-01-10T12:00:00.000ZclosestTo(target, dates)
Finds the date in an array that is closest to the target date.
Parameters:
target(Date) - The target date to compare againstdates(Date[]) - Array of dates to search
Returns: Date | null
const target = new Date("2024-06-15");
const dates = [
new Date("2024-06-10"),
new Date("2024-06-14"),
new Date("2024-06-20"),
];
closestTo(target, dates); // Returns date for June 14clampDate(date, min, max)
Clamps a date between minimum and maximum bounds.
Parameters:
date(Date) - The date to clampmin(Date) - Minimum allowed datemax(Date) - Maximum allowed date
Returns: Date (either original, min, or max)
const min = new Date("2024-06-01");
const max = new Date("2024-06-30");
clampDate(new Date("2024-06-15"), min, max); // June 15 (within bounds)
clampDate(new Date("2024-05-15"), min, max); // June 1 (clamped to min)
clampDate(new Date("2024-07-15"), min, max); // June 30 (clamped to max)datesUntil(start, end, step?)
Generates an array of dates between start and end dates with a specified step.
Parameters:
start(Date) - The start date (inclusive)end(Date) - The end date (inclusive)step(object, optional) - Step increment (default:{ days: 1 })years(number)months(number)weeks(number)days(number)hours(number)minutes(number)seconds(number)milliseconds(number)
Returns: Date[] - Array of Date objects
Examples:
const start = new Date("2024-01-01");
const end = new Date("2024-01-05");
// Daily range (default)
datesUntil(start, end);
// [2024-01-01, 2024-01-02, 2024-01-03, 2024-01-04, 2024-01-05]
// Chainable: chronal("2024-01-01").until(new Date("2024-01-05"))
// Weekly range
const weekEnd = new Date("2024-01-31");
datesUntil(start, weekEnd, { weeks: 1 });
// [2024-01-01, 2024-01-08, 2024-01-15, 2024-01-22, 2024-01-29]
// Chainable: chronal(start).until(weekEnd, { weeks: 1 })
// Monthly range
const monthEnd = new Date("2024-06-15");
datesUntil(new Date("2024-01-15"), monthEnd, { months: 1 });
// [2024-01-15, 2024-02-15, 2024-03-15, 2024-04-15, 2024-05-15, 2024-06-15]
// Every 3 days
datesUntil(start, new Date("2024-01-10"), { days: 3 });
// [2024-01-01, 2024-01-04, 2024-01-07, 2024-01-10]
// Hourly range
datesUntil(
new Date("2024-01-01T09:00:00Z"),
new Date("2024-01-01T17:00:00Z"),
{ hours: 2 },
);
// [09:00, 11:00, 13:00, 15:00, 17:00]Note: Month boundaries are handled intelligently. For example, starting on Jan 31 with monthly steps will yield Feb 29 (leap year), Mar 31, Apr 30, etc.
Date Difference
dateDiff(dateLeft, dateRight, unit)
Calculates the difference between two dates in the specified unit.
Parameters:
dateLeft(Date)dateRight(Date)unit('years' | 'months' | 'weeks' | 'days' | 'hours' | 'minutes' | 'seconds')
Returns: Number (can be negative)
con# `daysInMonth(date)`
### Date Information
#### `daysInMonth(date)`te("2024-01-20T12:00:00Z");
const date2 = new Date("2024-01-15T12:00:00Z");
dateDiff(date1, date2, "days"); // 5
dateDiff(date2, date1, "days"); // -5
dateDiff(date1, date2, "hours"); // 120Date Information
daysInMonth(date)
Returns the number of days in the month of the given date.
Returns: Number (28-31)
daysInMonth(new Date("2024-02-15")); // 29 (leap year)
daysInMonth(new Date("2023-02-15")); // 28
daysInMonth(new Date("2024-04-15")); // 30isLeapYear(date)
Checks if the year of the given date is a leap year.
isLeapYear(new Date("2024-01-01")); // true
isLeapYear(new Date("2023-01-01")); // false
isLeapYear(new Date("2000-01-01")); // true (divisible by 400)
isLeapYear(new Date("1900-01-01")); // false (divisible by 100 but not 400)getQuarter(date)
Returns the quarter (1-4) of the year for the given date.
Returns: 1 | 2 | 3 | 4
getQuarter(new Date("2024-01-15")); // 1 (Q1: Jan-Mar)
getQuarter(new Date("2024-04-15")); // 2 (Q2: Apr-Jun)
getQuarter(new Date("2024-07-15")); // 3 (Q3: Jul-Sep)
getQuarter(new Date("2024-10-15")); // 4 (Q4: Oct-Dec)weekOfYear(date)
Returns the week number of the year (1-53). Uses Sunday as the start of the week.
weekOfYear(new Date("2024-01-01")); // 1
weekOfYear(new Date("2024-01-08")); // 2
weekOfYear(new Date("2024-12-31")); // 53Localization
months(locale?, format?)
Returns an array of month names for the specified locale.
Parameters:
locale(string, optional) - Default: 'en-US'format('long' | 'short' | 'narrow', optional) - Default: 'long'
months("en-US", "long"); // ['January', 'February', ...]
months("en-US", "short"); // ['Jan', 'Feb', ...]
months("pt-BR", "long"); // ['janeiro', 'fevereiro', ...]weekdays(locale?, format?)
Returns an array of weekday names (Sunday to Saturday) for the specified locale.
Parameters: Same as months()
weekdays("en-US", "long"); // ['Sunday', 'Monday', 'Tuesday', ...]
weekdays("en-US", "short"); // ['Sun', 'Mon', 'Tue', ...]
weekdays("pt-BR", "long"); // ['domingo', 'segunda-feira', 'terça-feira', ...]Performance
Key optimizations:
- Format string caching (no repeated regex parsing)
- Fast UTC path (avoids expensive Intl.DateTimeFormat for UTC)
- Optimized padding functions
- Direct string concatenation
- Minimal object allocations (no temporary Date objects where possible)
- Short-circuit comparisons in isSame
- Efficient week and quarter calculations
Why Chronal?
Chronal offers a modern approach to date manipulation with a focus on simplicity and performance:
- Two APIs in one - Choose functional for tree-shaking or chainable for convenience
- Performance-focused - Optimized for common operations like formatting
- Zero dependencies - Built on native JavaScript APIs
- UTC-first - Reduces timezone-related bugs by defaulting to UTC
- Lightweight - Small bundle size, fully tree-shakeable
- Modern - ES modules, TypeScript support, immutable operations
Bundle Size Comparison
Functional API (tree-shakeable):
import { addTime, formatDate } from "chronal";
// Bundle: ~2-3KB (only imported functions)Chainable API:
import { chronal } from "chronal";
// Bundle: ~25-30KB (all methods included)Recommendation: Use functional API for libraries and performance-critical apps, chainable API for application code where DX matters more.
Chronal works well alongside other date libraries. Choose the tool that best fits your project's needs.
Design Principles
- UTC First - All operations work in UTC to avoid timezone surprises
- Immutability - Functions always return new Date objects
- Zero Dependencies - Leverages native Intl API for localization
- Performance - Optimized hot paths with caching
- Type Safety - Full TypeScript support
- Small API Surface - Easy to learn, hard to misuse
Browser Support
Chronal works in all modern browsers and JavaScript runtimes that support:
- ES6+ features
Intl.DateTimeFormatAPI- Native Date object
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT © André Luiz Gomes Filho
