npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dateface

v0.1.1

Published

Tiny, dependency-free, timezone-aware date formatting for JavaScript and TypeScript. Simple showDate(input, format) API.

Readme

dateface

Tiny, dependency-free, timezone-aware date formatting for JavaScript and TypeScript.

dateface gives you one obvious function, showDate(input, format), that turns a Date, an ISO string, or a Unix timestamp into a nicely formatted string in the user's local timezone, using only native Intl APIs under the hood.

import { showDate } from "dateface";

showDate(1757917800, "DD MMM YYYY");         // "15 Sep 2025"
showDate(1757917800000, "DD MMM YYYY");      // "15 Sep 2025" (ms works too)
showDate(new Date(), "YYYY-MM-DD HH:mm:ss");
showDate(date, "relative");                  // "2 hours ago"
  • Zero runtime dependencies. Just Intl.
  • Timezone-correct. Absolute instants are converted to the target zone; DST handled by the engine.
  • Seconds or milliseconds. Auto-detected, or set explicitly.
  • ESM + CommonJS, first-class TypeScript types, tree-shakeable.

Table of contents


Installation

pnpm add dateface
# or
npm install dateface
# or
yarn add dateface

Quick start

import { showDate } from "dateface";

// Unix seconds
showDate(1757917800, "DD MMM YYYY");                  // "15 Sep 2025"

// Unix milliseconds, same instant
showDate(1757917800000, "DD MMM YYYY");               // "15 Sep 2025"

// ISO string, rendered in the user's local timezone
showDate("2025-09-15T18:30:00Z", "DD MMM YYYY, hh:mm A");

// A Date object
showDate(new Date(), "DD/MM/YYYY");

// Presets
showDate(Date.now(), "datetime");                     // "15 Sep 2025, 6:30 PM"
showDate(Date.now(), "relative");                     // "just now"

// Explicit timezone / locale
showDate(1757917800, "DD MMM YYYY, HH:mm", {
  timezone: "Asia/Kolkata",
  locale: "en-IN",
});                                                    // "15 Sep 2025, 12:00"

Supported inputs

type DateInput = Date | string | number;

| Input | Notes | | -------- | ----------------------------------------------------------------------------------- | | Date | Used as-is. An invalid Date throws. | | string | Parsed by the native Date parser. Prefer ISO-8601 ("2025-09-15T18:30:00Z"). | | number | Unix timestamp in seconds or milliseconds, auto-detected (see below). |

Seconds vs. milliseconds

A numeric input is interpreted by magnitude: values with an absolute value below 1e11 are treated as seconds, otherwise milliseconds. This cleanly distinguishes a normal seconds timestamp (1757917800, year 2025) from a milliseconds one (1757917800000, year 2025), and both resolve to the same instant.

The distinction is inherently ambiguous for small numbers, so you can force it:

showDate(1000, "YYYY-MM-DD HH:mm:ss", { unit: "milliseconds" }); // 1970-01-01 00:00:01
showDate(1000, "YYYY-MM-DD HH:mm:ss", { unit: "seconds" });      // 1970-01-01 00:16:40

0, negative values (pre-1970), and dates around the epoch all work.

Formatting tokens

Build any pattern from these tokens. Values shown for 2025-09-15T06:30:05Z rendered in UTC (a Monday).

| Token | Meaning | Example | | ------ | -------------------------- | ----------- | | YYYY | 4-digit year | 2025 | | YY | 2-digit year | 25 | | MMMM | Month, full (localized) | September | | MMM | Month, short (localized) | Sep | | MM | Month, 2-digit | 09 | | M | Month | 9 | | DD | Day of month, 2-digit | 15 | | D | Day of month | 15 | | dddd | Weekday, full (localized) | Monday | | ddd | Weekday, short (localized) | Mon | | HH | Hour 24h, 2-digit | 06 | | H | Hour 24h | 6 | | hh | Hour 12h, 2-digit | 06 | | h | Hour 12h | 6 | | mm | Minute, 2-digit | 30 | | m | Minute | 30 | | ss | Second, 2-digit | 05 | | s | Second | 5 | | A | Meridiem, uppercase | AM | | a | Meridiem, lowercase | am |

Anything that isn't a token is emitted verbatim (/, -, :, spaces, etc.).

Escaping literal text

Wrap literal text in [...] so letters aren't interpreted as tokens:

showDate(date, "DD MMM YYYY [at] HH:mm"); // "15 Sep 2025 at 06:30"
showDate(date, "[Year] YYYY");            // "Year 2025"

Note on MMMM / MMM / dddd / ddd: these are localized via options.locale. A / a are always the ASCII strings AM/PM (and lowercase) for predictability. Use the datetime / time presets if you want locale-aware meridiems.

Common patterns

showDate(date, "DD/MM/YYYY");            // 15/09/2025
showDate(date, "DD-MM-YYYY");            // 15-09-2025
showDate(date, "DD MMM YYYY");           // 15 Sep 2025
showDate(date, "DD MMMM YYYY");          // 15 September 2025
showDate(date, "MMM DD, YYYY");          // Sep 15, 2025
showDate(date, "YYYY-MM-DD");            // 2025-09-15
showDate(date, "DD MMM YYYY, hh:mm A");  // 15 Sep 2025, 06:30 AM
showDate(date, "YYYY-MM-DD HH:mm:ss");   // 2025-09-15 06:30:05

Presets

Pass a preset name instead of a token string:

| Preset | Output (example) | | ------------ | ---------------------- | | "short" | 15 Sep 2025 | | "long" | 15 September 2025 | | "datetime" | 15 Sep 2025, 6:30 PM | | "time" | 6:30 PM | | "relative" | 2 hours ago |

showDate(date, "short");
showDate(date, "datetime");
showDate(date, "relative");

Presets expand to token patterns (except relative); you can inspect them via the exported PRESET_PATTERNS.

Relative time

showDate(date, "relative") produces human-friendly output. It's implemented as a preset (not a separate function) so the API stays uniform: one function to learn. The wording comes from Intl.RelativeTimeFormat, so it's locale-aware and correctly pluralized; the sub-minute case is special-cased as "just now".

showDate(t, "relative");              // "just now" | "2 minutes ago" | "yesterday" | ...
showDate(future, "relative");         // "in 3 hours" | "tomorrow" | ...
showDate(t, "relative", { now });     // pass a reference point (great for SSR / tests)

| Elapsed | Output | | ------------ | --------------------------- | | < 45 s | just now | | 1-44 min | N minutes ago | | ~1-21 h | N hours ago | | ~1 day | yesterday | | 2-6 days | N days ago | | ~1-3 weeks | N weeks ago | | ~1-11 months | N months ago | | >= ~1 year | last year / N years ago |

A stand-alone formatRelative(date, now, locale) is also exported if you prefer to call it directly.

Timezone behavior

A Unix timestamp / ISO instant is an absolute point in time. dateface:

  1. Parses the input.
  2. Normalizes it to an absolute instant (Date).
  3. Determines the target timezone (options.timezone or the runtime default).
  4. Converts the instant into that timezone via Intl.
  5. Formats the resulting local date/time.

Timestamps are never interpreted as local time, and DST transitions are handled by the engine's IANA database.

const t = 1757917800; // 2025-09-15T06:30:00Z

showDate(t, "YYYY-MM-DD HH:mm", { timezone: "UTC" });              // 2025-09-15 06:30
showDate(t, "YYYY-MM-DD HH:mm", { timezone: "Asia/Kolkata" });     // 2025-09-15 12:00
showDate(t, "YYYY-MM-DD HH:mm", { timezone: "America/New_York" }); // 2025-09-15 02:30
showDate(t, "YYYY-MM-DD HH:mm", { timezone: "Europe/London" });    // 2025-09-15 07:30

// Near midnight the local date can differ from UTC:
showDate("2025-09-15T02:00:00Z", "YYYY-MM-DD", { timezone: "America/New_York" });
// "2025-09-14"

If no timezone is given, the default is:

Intl.DateTimeFormat().resolvedOptions().timeZone
  • Browser: the end-user's own timezone. You get correct local output with zero config.
  • Node.js: the server's timezone (from TZ or the OS). See below.

If the environment can't resolve a zone, it falls back to "UTC". An unsupported timezone value throws a ShowDateError.

Locale

options.locale (a BCP-47 tag) controls localized month/weekday names and relative wording. It defaults to "en-US".

showDate(t, "DD MMMM YYYY", { locale: "en-US" });  // 15 September 2025
showDate(t, "DD MMM YYYY",  { locale: "en-GB" });  // 15 Sept 2025
showDate(t, "DD MMMM YYYY", { locale: "fr-FR" });  // 15 septembre 2025
showDate(t, "relative", { locale: "es", now });    // hace 2 horas

No locale is hard-coded into the core; en-US is only the default.

Options

interface ShowDateOptions {
  timezone?: string;                          // IANA name; default = runtime zone
  locale?: string;                            // BCP-47; default = "en-US"
  unit?: "auto" | "seconds" | "milliseconds"; // numeric input; default = "auto"
  now?: Date | string | number;               // reference point for "relative"
}

The third argument is always optional; the common case stays showDate(input, format).

Browser usage

import { showDate } from "dateface";

// Automatically uses the visitor's local timezone.
document.querySelector("#published")!.textContent =
  showDate(post.publishedAt, "DD MMM YYYY, hh:mm A");

Node.js usage

A server cannot know a remote browser user's timezone. The runtime default is the server's timezone, which is rarely what you want when rendering for users. Pass the timezone explicitly (e.g. from the user's profile or an HTTP hint):

import { showDate } from "dateface";

function renderForUser(instant: number, userTimeZone: string) {
  return showDate(instant, "DD MMM YYYY, HH:mm", { timezone: userTimeZone });
}

renderForUser(1757917800, "America/New_York"); // "15 Sep 2025, 02:30"

For deterministic server-side relative rendering, pass now explicitly.

Error handling

dateface never silently returns "Invalid Date". Invalid input throws a typed ShowDateError:

import { showDate, ShowDateError } from "dateface";

try {
  showDate("invalid-date", "DD MMM YYYY");
} catch (err) {
  if (err instanceof ShowDateError) {
    console.error(err.message); // Unable to parse date string: "invalid-date". ...
  }
}

Throwing cases: unparseable strings, invalid Date objects, non-finite / out-of-range numbers, unsupported input types, and unknown timezones.

API reference

showDate(input, format, options?) => string

The main entry point. Also available as the default export.

  • input: Date | string | number
  • format: "short" | "long" | "datetime" | "time" | "relative" | string
  • options?: ShowDateOptions

formatRelative(date: Date, now: Date, locale: string) => string

Low-level relative formatter used by the "relative" preset.

getDefaultTimeZone() => string

The runtime's resolved IANA timezone, or "UTC" as a fallback.

isValidTimeZone(tz: string) => boolean

Whether the runtime's Intl supports the given zone.

PRESET_PATTERNS

Record mapping preset names (except relative) to their token patterns.

ShowDateError

Error subclass thrown for all invalid input.

Types

DateInput, DateFormat, FormatPreset, TimestampUnit, ShowDateOptions are all exported.

Why this package exists

Most date formatting either drags in a large dependency (Moment, and even smaller libs add weight) or forces you to wrestle with Intl.DateTimeFormat's option objects every time. The everyday need is simply: "show me this instant in the user's timezone, in this shape."

dateface is exactly that: a single, memorable function built entirely on native Intl, so it stays tiny, correct across timezones and DST, and dependency-free.

License

MIT