Skip to content

andreluizsgf/chronal

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

87 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Chronal

A tiny, fast, and modern date utility library for JavaScript/TypeScript with zero dependencies.

Gzip Size NPM Version JSR Version Coverage License

Features

  • 🪶 Lightweight - Zero dependencies, minimal bundle size
  • 🌍 i18n Support - Locale-aware formatting with Intl API
  • 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

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 format
  • formatString (string) - Format pattern with tokens
  • options (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 parse
  • format (string, optional) - Format pattern (e.g., "YYYY-MM-DD", "DD/MM/YYYY")
  • options (object, optional) - Parsing options
    • tz (string) - IANA timezone (e.g., 'America/Sao_Paulo')

Returns: Date object

Timezone Behavior:

When parsing date strings, parseDate follows these rules:

  1. Explicit timezone (e.g., Z or +03:00) - Always respected, ignores config.timezone
  2. No timezone - Uses config.timezone or the tz option 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 Paulo

Supported Tokens:

  • YYYY - 4-digit year
  • MM - 2-digit month
  • DD - 2-digit day
  • HH - 2-digit hour (24h)
  • mm - 2-digit minute
  • ss - 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 time

Manipulation

addTime(date, options)

Adds specified time units to a date.

Parameters:

  • date (Date) - The original date
  • options (object) - Time units to add
    • years (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.000Z

subtract(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 from
  • unit ('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)

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"); // 14

setUnit(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 modify
  • unit ('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:22Z

Start & End of Period

startOf(date, unit)

Returns the start of the specified time unit.

Parameters:

  • date (Date) - The original date
  • unit ('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.000Z

endOf(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.999Z

Comparison

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); // true

isBefore(dateLeft, dateRight)

Checks if the first date is before the second date.

isBefore(date2, date1); // true

isEqual(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); // true

isSame(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 check
  • start (Date) - Start of range
  • end (Date) - End of range
  • inclusivity ('[]' | '()' | '[)' | '(]', 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")); // false

isTomorrow(date)

Checks if a date is tomorrow (in UTC).

const tomorrow = new Date(Date.now() + 86400000);
isTomorrow(tomorrow); // true

isYesterday(date)

Checks if a date is yesterday (in UTC).

const yesterday = new Date(Date.now() - 86400000);
isYesterday(yesterday); // true

isValidDate(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)); // false

Relative 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.000Z

minDate(...dates)

Returns the earliest date from the given dates.

minDate(date1, date2, date3); // 2024-01-10T12:00:00.000Z

closestTo(target, dates)

Finds the date in an array that is closest to the target date.

Parameters:

  • target (Date) - The target date to compare against
  • dates (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 14

clampDate(date, min, max)

Clamps a date between minimum and maximum bounds.

Parameters:

  • date (Date) - The date to clamp
  • min (Date) - Minimum allowed date
  • max (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"); // 120

Date 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")); // 30

isLeapYear(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")); // 53

Localization

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

  1. UTC First - All operations work in UTC to avoid timezone surprises
  2. Immutability - Functions always return new Date objects
  3. Zero Dependencies - Leverages native Intl API for localization
  4. Performance - Optimized hot paths with caching
  5. Type Safety - Full TypeScript support
  6. 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.DateTimeFormat API
  • Native Date object

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT © André Luiz Gomes Filho

Links

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors