datekit-js
v1.0.0
Published
A beginner-friendly date formatting library — simpler than moment.js, zero dependencies
Maintainers
Readme
datekit-js 📅
Tagline: "Date formatting that just makes sense."
datekit-js is a tiny, dependency-free toolkit for formatting, parsing, comparing, and nudging dates in TypeScript or JavaScript. It wraps the built-in Date object with predictable helpers so you can ship features without pulling in a heavyweight legacy library.
Why datekit-js?
| Capability | datekit-js | moment.js | date-fns | | --- | --- | --- | --- | | Approximate minified footprint | ~3 KB (library code only; your bundle may vary) | ~70 KB (minified, not tree-shaken) | Depends on imports (each function adds a slice) | | Tree-shakable | Yes (pure functions + named exports) | No (mutable singleton design) | Yes | | Zero runtime dependencies | Yes | No | Yes | | Learning curve | Gentle (small surface area) | Medium (large API + mutable concepts) | Medium (many modules to discover) | | Beginner friendly | Yes (plain functions, clear errors) | Dated patterns (global locale state) | Yes (modern, modular style) |
moment.js remains a classic, but its size and mutability surprises trip up newcomers. date-fns is excellent yet sprawling. datekit-js aims for the middle: just enough API to cover day-to-day UI work without importing an entire calendar science textbook.
Installation
npm install datekit-jsyarn add datekit-jspnpm add datekit-jsQuick start
import { format, parse, timeAgo } from "datekit-js";
const publishedAt = parse("2024-06-15", "YYYY-MM-DD");
const label = format(publishedAt, "MMMM D, YYYY");
const relative = timeAgo(publishedAt);
console.log(label); // "June 15, 2024"
console.log(relative); // e.g. "11 months ago" (depends on "now")That is enough to render a blog timestamp plus a human-friendly relative label.
Core concepts
DateInput
Many helpers accept a DateInput, which is simply:
type DateInput = Date | string | number;- Pass a
Datewhen you already constructed one. - Pass an ISO string (for example
"2024-01-05T12:00:00") when data arrives from JSON. - Pass a Unix timestamp in milliseconds when you stored
Date.now()in your database.
Internally, datekit-js clones these values into a fresh Date so you never accidentally reuse a mutated instance.
Immutability
add, subtract, startOf, and endOf always return new Date objects. The originals stay untouched, which keeps React state updates predictable.
API reference (cheat sheet)
| Function | What it does |
| --- | --- |
| format(date, pattern) | Prints a date with literal text + tokens. |
| parse(text, pattern?) | Reads ISO strings by default, or a custom pattern. |
| timeAgo(date) | "3 hours ago", "yesterday", "just now", … |
| timeUntil(date) | "in 5 minutes", "tomorrow", "in 2 weeks", … |
| add(date, amount, unit) | Moves forward on the calendar clock. |
| subtract(date, amount, unit) | Moves backward (implemented as add with a negative amount). |
| startOf(date, unit) | Snaps to the beginning of a year/month/week/day/etc. |
| endOf(date, unit) | Snaps to the last millisecond inside that unit. |
| isBefore / isAfter | Strict ordering checks. |
| isSame(a, b, unit?) | Equality down to milliseconds, or for a whole unit bucket. |
| diff(a, b, unit) | Signed distance from a to b in the requested unit. |
| isValid(value) | Safe guard for untrusted JSON. |
| isLeapYear / isWeekend / isToday | Calendar helpers. |
For exhaustive signatures, thrown errors, and extra examples, read docs/api-reference.md.
Format tokens
| Token | Meaning | Example output (Jan 5, 2024 @ 15:07:09 local) |
| --- | --- | --- |
| YYYY | Four-digit year | 2024 |
| YY | Two-digit year | 24 |
| MMMM | Full month | January |
| MMM | Short month | Jan |
| MM | Padded month | 01 |
| M | Month without padding | 1 |
| DD | Padded day | 05 |
| D | Day without padding | 5 |
| dddd | Full weekday | Friday |
| ddd | Short weekday | Fri |
| HH | 24-hour clock (padded) | 15 |
| h | 12-hour clock (no padding) | 3 |
| hh | 12-hour clock (padded) | 03 |
| mm | Minutes | 07 |
| ss | Seconds | 09 |
| A | Uppercase meridiem | PM |
| a | Lowercase meridiem | pm |
| X | Unix seconds | 1704473229 |
| x | Unix milliseconds | 1704473229123 |
Anything that is not a token is copied literally, so slashes, commas, and words appear exactly as written.
Recipes
How do I display a blog post date?
import { parse, format } from "datekit-js";
const post = parse(metadata.publishedOn); // ISO string from your CMS
const pretty = format(post, "MMMM D, YYYY 'at' h:mm A");How do I show a countdown?
import { timeUntil } from "datekit-js";
const launch = new Date("2026-12-31T23:59:59");
const label = timeUntil(launch);Pair timeUntil with setInterval in the browser to refresh the label.
How do I check if a date is in the past?
import { isBefore } from "datekit-js";
const due = new Date("2024-01-01");
const overdue = isBefore(due, new Date());Common mistakes (and how datekit helps)
Mutating shared
Dateinstances. Native methods likesetMonthmutate in place. datekit-js manipulation helpers always return a newDate, so accidental shared state is harder to introduce.Feeding
Date.parserandom strings.parsethrows early with adatekit:prefix when a string cannot be understood, which is easier to debug than a silentInvalid Date.Mixing up months (0-indexed) and UI copy (1-indexed).
formattokensMM/Mprint human-friendly month numbers while internally still respecting the nativeDaterules.Assuming "add one month" always lands on the same day number. JavaScript rolls overflowing days forward (for example, January 31 + 1 month becomes March 2 in non-leap years). datekit-js does not hide that engine behaviour; write an extra guard if your product needs business-month semantics.
Documentation map
docs/getting-started.md— onboarding for first-timeDateusers.docs/format-tokens.md— exhaustive token list with commentary.docs/api-reference.md— formal signatures, thrown errors, and examples.docs/examples.md— cookbook snippets for real UI flows.
License
MIT © datekit-js contributors
