Date Library#

Buntok ships a complete, dependency-free port of the date-fns v4 API across three subpaths. It behaves exactly like date-fns (parity-tested against date-fns@4.4.0), but you never have to install it.

Subpath imports
The date library is not exported from the root barrel - always import from @buntok/core/date, @buntok/core/date/fp, or @buntok/core/date/locale.
SubpathExportsContents
@buntok/core/date250Format & parse, distances, relative time, intervals & durations, comparisons, start/end of, math, weeks & quarters, ISO/RFC helpers
@buntok/core/date/fp396Curried variants of every function - arguments reversed for partial application
@buntok/core/date/locale95Locale objects: id, en-US, ja, ar, ru, zh-CN, de, pt-BR, ...

Format & parse#

All date-fns format tokens are supported (P, PPPP, EEEE, HH:mm, ...), plus strict parsing and ISO helpers:

typescript
import {
  format, parse, parseISO, isValid, formatISO,
} from "@buntok/core/date";

const date = parseISO("2024-10-01T14:30:45Z");
isValid(date);                                   // true

// Outputs below are shown for a server in UTC+7
format(date, "EEEE, d MMMM yyyy 'pukul' HH:mm"); // "Tuesday, 1 October 2024 pukul 21:30"
format(date, "PPpp");                            // "10/01/2024, 9:30:45 PM"
formatISO(date);                                 // "2024-10-01T21:30:45+07:00"

// Reference date fills in missing fields
parse("10.01.2024", "MM.dd.yyyy", new Date());

Distances & relative time#

typescript
import {
  formatDistance, formatDistanceStrict, formatRelative,
  addDays, subDays, differenceInCalendarDays, getWeek, getQuarter,
} from "@buntok/core/date";

const now = new Date();

formatDistance(subDays(now, 10), now, { addSuffix: true });
// "10 days ago"

formatDistanceStrict(addDays(now, 14), now, { unit: "day", addSuffix: true });
// "in 14 days"

formatRelative(addDays(now, 1), now);
// e.g. "tomorrow at 20:15"

differenceInCalendarDays(now, new Date("2024-10-01")); // calendar-day difference
getWeek(now);                                          // week of year
getQuarter(now);                                       // 1–4

Intervals & durations#

typescript
import {
  intervalToDuration, isWithinInterval, eachDayOfInterval,
} from "@buntok/core/date";

intervalToDuration({ start: date, end: addDays(date, 400) });
// { years: 1, months: 1, days: 4, hours: 0, ... }

isWithinInterval(date, { start: now, end: addDays(now, 7) }); // true / false
eachDayOfInterval({ start: now, end: addDays(now, 3) });      // Date[4]

Functional style (fp)#

Every export has a curried variant on @buntok/core/date/fp. Arguments are reversed relative to the main API so the varying argument can be supplied last, and the argument list can be split across calls:

typescript
import {
  format, addDays, addWeeks, formatWithOptions, nextMonday,
} from "@buntok/core/date/fp";

const now = new Date();

addDays(10)(now);                 // main: addDays(now, 10) - same result
addDays()(10)(now);               // curried chain - same result
addDays(10, now);                 // full application in one call

const dayName = format("EEEE");   // reusable partial: date → weekday
dayName(now);                     // e.g. "Friday"

format("PP")(addWeeks(2)(now));   // composition: e.g. "Oct 16, 2026"
nextMonday(now);                  // arity-1 functions take the date directly

import { id } from "@buntok/core/date/locale";
formatWithOptions({ locale: id }, "EEEE, d MMMM yyyy")(now);
// "Jumat, 2 Oktober 2026"

Locales#

95 locales ship on @buntok/core/date/locale. Pass any of them via the { locale } option to format, formatRelative, formatDistance, getWeek, and friends:

typescript
import * as locales from "@buntok/core/date/locale";
import { id, ja, ar, zhCN } from "@buntok/core/date/locale";
import { format, formatRelative, getWeek, addDays } from "@buntok/core/date";

Object.keys(locales).length;                         // 95

const now = new Date();
const tomorrow = addDays(now, 1);

format(now, "EEEE, d MMMM yyyy", { locale: id });
// e.g. "Jumat, 2 Oktober 2026"

format(now, "EEEE, d MMMM yyyy", { locale: ja });
// e.g. "金曜日, 2 10月 2026"
formatRelative(tomorrow, now, { locale: ja });
// localized relative pattern (ja)
getWeek(now, { locale: ar });                        // locale week rules

To discover a code, iterate Object.keys(locales); each object exposes a canonical code property (e.g. "zh-CN") you can use as a registry key:

typescript
const registry: Record<string, (typeof locales)[keyof typeof locales]> = {};
for (const locale of Object.values(locales)) {
  registry[locale.code] = locale;
}

registry["id"];    // Indonesian locale
registry["zh-CN"]; // Simplified Chinese

Full Example#

typescript
import { format, formatDistance, subDays, addDays } from "@buntok/core/date";
import { id } from "@buntok/core/date/locale";

// API endpoint summarizing this week in Indonesian
app.get("/reports/week", (ctx) => {
  const now = new Date();
  const since = subDays(now, 7);

  return ctx.json({
    today: format(now, "EEEE, d MMMM yyyy", { locale: id }), // "Jumat, 2 Oktober 2026"
    window: formatDistance(since, now, { addSuffix: true, locale: id }), // "7 hari yang lalu"
    days: [...Array(7)].map((_, i) => format(addDays(since, i), "d MMM", { locale: id })),
    // e.g. ["25 Sep", "26 Sep", ...]
  });
});

Which import should I use?#

NeedUse
Quick one-offs in app code@buntok/core root helpers (formatDate, timeAgo, ...)
Full formatting / parsing / comparisons@buntok/core/date
Pipelines, reusable partials, point-free style@buntok/core/date/fp
Non-English output, locale week rules{ locale } option from @buntok/core/date/locale
Timezone conversion & formattingTimezone helpers (Intl-based)
Zero dependencies
date-fns is only a dev dependency of the framework used for parity tests - your application never installs it, and the root @buntok/core barrel stays slim.