@theghost34/time_formater
v1.0.4
Published
Tiny zero-dependency date formatter with i18n and relative-time support (en/fr/ar).
Maintainers
Readme
Table of Contents
Features
- Zero dependencies — nothing to audit, nothing to break.
- Token-based formatting —
YYYY,MM,DD,HH,mm,ss,dddd,Month,Q,W,Zand more. - Relative time —
"2 hours ago","in 5 minutes","Yesterday","Tomorrow". - i18n built-in — English, French, and Arabic (with full singular / dual / plural rules).
- Extensible — register any locale at runtime with
addLocale. - UTC mode — pass
{ utc: true }to format in UTC instead of local time. - TypeScript — ships
.d.tsdeclarations, no@typespackage needed. - ESM + CJS — works in Node.js, bundlers, and edge runtimes.
Installing
Using npm:
$ npm install @theghost34/time_formaterUsing yarn:
$ yarn add @theghost34/time_formaterUsing pnpm:
$ pnpm add @theghost34/time_formaterUsing bun:
$ bun add @theghost34/time_formaterOnce installed, import with import or require:
import { formatTime, formatRelativeTime } from '@theghost34/time_formater';const { formatTime, formatRelativeTime } = require('@theghost34/time_formater');Quick Start
import { formatTime, formatRelativeTime } from '@theghost34/time_formater';
const now = new Date();
formatTime(now, 'YYYY-MM-DD'); // "2026-04-12"
formatTime(now, 'dddd, DD Month YYYY', 'fr'); // "dimanche, 12 avril 2026"
formatTime(now, 'hh:mm A'); // "09:30 AM"
formatRelativeTime(now); // "Today"
formatRelativeTime(new Date(Date.now() - 3_600_000)); // "1 hour ago"
formatRelativeTime(new Date(Date.now() + 7_200_000)); // "in 2 hours"API
formatTime
formatTime(
input : Date | string | number,
format ?: string, // default: "YYYY-MM-DD HH:mm:ss"
lang ?: string, // default: "en"
options?: { utc?: boolean }
): stringFormats a date using a token-based format string (see Format Tokens below).
const d = new Date('2026-04-09T15:30:45');
formatTime(d, 'YYYY-MM-DD') // "2026-04-09"
formatTime(d, 'HH:mm:ss') // "15:30:45"
formatTime(d, 'hh:mm A') // "03:30 PM"
formatTime(d, 'dddd, DD Month YYYY') // "Thursday, 09 April 2026"
formatTime(d, 'dddd, DD Month YYYY', 'fr') // "jeudi, 09 avril 2026"
formatTime(d, 'dddd, DD Month YYYY', 'ar') // "الخميس, 09 أبريل 2026"
formatTime(d, 'Qo quarter, week WW of YYYY') // "2nd quarter, week 15 of 2026"
formatTime(d, 'Z') // "+01:00"
// UTC mode
const utc = new Date('2026-04-09T22:00:00Z');
formatTime(utc, 'HH:mm', 'en', { utc: true }) // "22:00"
// Invalid input returns a localized error string
formatTime('not-a-date') // "Invalid Date"
formatTime('not-a-date', 'YYYY', 'fr') // "Date invalide"formatRelativeTime
formatRelativeTime(
input : Date | string | number,
lang ?: string, // default: "en"
options?: {
now ?: Date; // reference point — defaults to new Date()
calendar?: boolean; // show today/yesterday/tomorrow labels — default: true
}
): stringReturns a human-readable relative-time string.
Note: Calendar labels (
"Today","Yesterday","Tomorrow") compare calendar days, not elapsed milliseconds. A date at 11:45 PM is correctly labelled"Yesterday"even if it was only 20 minutes ago.
const now = new Date('2026-04-09T12:00:00Z');
// Calendar labels
formatRelativeTime(now, 'en', { now }) // "Today"
formatRelativeTime(new Date('2026-04-08T12:00:00Z'), 'en', { now }) // "Yesterday"
formatRelativeTime(new Date('2026-04-10T12:00:00Z'), 'en', { now }) // "Tomorrow"
// Past
formatRelativeTime(new Date(+now - 30_000), 'en', { now }) // "30 seconds ago"
formatRelativeTime(new Date(+now - 3_600_000), 'en', { now }) // "1 hour ago"
formatRelativeTime(new Date(+now - 3_600_000), 'fr', { now }) // "il y a 1 heure"
formatRelativeTime(new Date(+now - 3_600_000), 'ar', { now }) // "منذ ساعة"
// Future
formatRelativeTime(new Date(+now + 7_200_000), 'en', { calendar: false, now }) // "in 2 hours"
formatRelativeTime(new Date(+now + 7_200_000), 'fr', { calendar: false, now }) // "dans 2 heures"
formatRelativeTime(new Date(+now + 7_200_000), 'ar', { calendar: false, now }) // "بعد ساعتين"addLocale
addLocale(code: string, def: LocaleDef): voidRegisters a new locale (or overrides an existing one). All fields are optional.
interface LocaleDef {
months?: { long: string[]; short: string[] };
days?: { long: string[]; short: string[]; min: string[] };
relative?: {
// Past strings
seconds?(v: number): string;
minutes?(v: number): string;
hours?(v: number): string;
days?(v: number): string;
weeks?(v: number): string;
months?(v: number): string;
years?(v: number): string;
// Future strings
in_seconds?(v: number): string;
in_minutes?(v: number): string;
in_hours?(v: number): string;
in_days?(v: number): string;
in_weeks?(v: number): string;
in_months?(v: number): string;
in_years?(v: number): string;
// Labels
yesterday?: string;
today? : string;
tomorrow? : string;
invalid? : string;
};
}See Custom Locales for a full example.
parseDate
parseDate(input: Date | string | number): Date | nullSafely parses any date-like value. Returns null instead of an invalid Date object.
parseDate(new Date()) // Date object
parseDate('2026-04-09') // Date object
parseDate(1774176000000) // Date object
parseDate('not a date') // nullFormat Tokens
| Token | Example output | Description |
|---------|-------------------------|-------------------------------------|
| YYYY | 2026 | 4-digit year |
| YY | 26 | 2-digit year |
| MM | 04 | Month, zero-padded |
| Month | April / avril | Full month name (localized) |
| Mon | Apr / avr. | Short month name (localized) |
| DD | 09 | Day of month, zero-padded |
| d | 9 | Day of month, no padding |
| HH | 15 | Hours 24 h, zero-padded |
| hh | 03 | Hours 12 h, zero-padded |
| A | PM | AM / PM |
| a | pm | am / pm |
| mm | 30 | Minutes, zero-padded |
| ss | 45 | Seconds, zero-padded |
| dddd | Thursday / jeudi | Full weekday name (localized) |
| ddd | Thu / jeu. | Short weekday name (localized) |
| dd | Th / je | Minimal weekday name (localized) |
| Q | 2 | Quarter (1–4) |
| Qo | 2nd / 2e | Ordinal quarter (localized) |
| W | 15 | ISO 8601 week number |
| WW | 15 | ISO 8601 week number, zero-padded |
| Z | +01:00 | Timezone offset |
| ZZ | +0100 | Timezone offset, compact |
Supported Locales
| Code | Language | Notes |
|------|----------|-------------------------------------------------------------|
| en | English | Standard singular / plural |
| fr | French | Standard singular / plural, invariant "mois" |
| ar | Arabic | Full singular / dual / plural 3–10 / plural 11+ rules |
Custom Locales
import { addLocale, formatTime, formatRelativeTime } from '@theghost34/time_formater';
addLocale('de', {
months: {
long: ['Januar','Februar','März','April','Mai','Juni',
'Juli','August','September','Oktober','November','Dezember'],
short: ['Jan','Feb','Mär','Apr','Mai','Jun',
'Jul','Aug','Sep','Okt','Nov','Dez']
},
days: {
long: ['Sonntag','Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag'],
short: ['So','Mo','Di','Mi','Do','Fr','Sa'],
min: ['So','Mo','Di','Mi','Do','Fr','Sa']
},
relative: {
seconds: (v) => `vor ${v} Sekunde${v !== 1 ? 'n' : ''}`,
minutes: (v) => `vor ${v} Minute${v !== 1 ? 'n' : ''}`,
hours: (v) => `vor ${v} Stunde${v !== 1 ? 'n' : ''}`,
days: (v) => `vor ${v} Tag${v !== 1 ? 'en' : ''}`,
weeks: (v) => `vor ${v} Woche${v !== 1 ? 'n' : ''}`,
months: (v) => `vor ${v} Monat${v !== 1 ? 'en' : ''}`,
years: (v) => `vor ${v} Jahr${v !== 1 ? 'en' : ''}`,
in_seconds: (v) => `in ${v} Sekunde${v !== 1 ? 'n' : ''}`,
in_minutes: (v) => `in ${v} Minute${v !== 1 ? 'n' : ''}`,
in_hours: (v) => `in ${v} Stunde${v !== 1 ? 'n' : ''}`,
in_days: (v) => `in ${v} Tag${v !== 1 ? 'en' : ''}`,
in_weeks: (v) => `in ${v} Woche${v !== 1 ? 'n' : ''}`,
in_months: (v) => `in ${v} Monat${v !== 1 ? 'en' : ''}`,
in_years: (v) => `in ${v} Jahr${v !== 1 ? 'en' : ''}`,
today: 'Heute',
yesterday: 'Gestern',
tomorrow: 'Morgen',
invalid: 'Ungültiges Datum'
}
});
formatTime(new Date('2026-04-09'), 'dddd, DD Month YYYY', 'de') // "Donnerstag, 09 April 2026"
formatRelativeTime(new Date(), 'de') // "Heute"TypeScript
The package ships with full type declarations — no @types install needed.
import { formatTime, formatRelativeTime, addLocale, parseDate } from '@theghost34/time_formater';
import type { DateInput, LocaleCode, LocaleDef } from '@theghost34/time_formater';
const formatted: string = formatTime(new Date(), 'YYYY-MM-DD', 'fr');
const parsed: Date | null = parseDate('2026-04-09');