@verifyhash/human-time
v0.1.0
Published
Zero-dependency human-readable relative time ('5 minutes ago', 'in 3 days') plus compact ms-style duration format/parse ('2h30m' <-> ms) for Node.js. English-only.
Maintainers
Readme
human-time
A tiny, zero-dependency Node.js library for two everyday time chores:
- Relative phrases — turn a timestamp into
"5 minutes ago"or"in 3 days". - Compact durations — turn milliseconds into
"2h30m"and back again.
No install step, no node_modules, no network, no servers. One file:
src/index.js. Node 12+.
English only. Output is fixed English. There is no locale/pluralization layer here on purpose — if you need localized phrasing, reach for
Intl.RelativeTimeFormator a full i18n library. This module optimizes for being small, dependency-free, and predictable.
Who it's for
Anyone rendering timestamps or durations in a CLI, log line, dashboard, or
small web app who wants friendly output without pulling in moment, dayjs,
date-fns, or ms. It is deliberately distinct from the sibling
iso-duration library: iso-duration parses/formats ISO 8601 durations
(PT1H30M) and does calendar-correct date arithmetic; human-time does
approximate human phrasing and compact ms-style strings.
Install / use
Copy the folder in, or require it directly — there is nothing to build.
const { relative, format, parse } = require('human-time'); // main = src/index.jsAPI
relative(from, to?) -> string
Describes from as seen from the reference to. Both arguments accept a
Date or epoch-milliseconds (a number). to defaults to Date.now()
when omitted — so the common one-argument call just works:
relative(Date.now() - 5 * 60 * 1000); // "5 minutes ago"
relative(Date.now() + 90 * 60 * 1000); // "in 2 hours"
relative(new Date('2000-01-01'), new Date('2000-01-01')); // "just now"Direction is chosen so single-argument calls read naturally: when from is
earlier than to you get past tense ("N ... ago"); when from is later you
get future tense ("in N ..."). Anything under one second, in either
direction, is "just now".
The threshold ladder (each band rounds to its nearest whole unit):
| Gap | Output examples |
| ----------------------- | ---------------------------- |
| < 1s | just now |
| 1s … < 1m | 1 second ago … 59 seconds ago |
| 1m … < 1h | 5 minutes ago, in 12 minutes |
| 1h … < 1d | 3 hours ago |
| 1d … < 1w | 3 days ago |
| 1w … < 1 month | 2 weeks ago |
| 1 month … < 1 year | 3 months ago |
| >= 1 year | 2 years ago, in 5 years |
Honest limits: months and years use average Gregorian lengths
(30.436875 and 365.2425 days), so "3 months ago" is approximate, never
calendar-exact — if you need "exactly 3 calendar months", use date arithmetic
(e.g. the iso-duration sibling), not this. Values sit in a single band and
round, so a 25-hour gap reads "1 day ago", not "1 day 1 hour ago".
format(ms) -> string
Compact, ms-package-style duration string. Emits every non-zero component
from days down to milliseconds, largest first, so it round-trips through
parse:
format(9_000_000); // "2h30m"
format(24*3600*1000 + 4*3600*1000); // "1d4h"
format(45_000); // "45s"
format(500); // "500ms"
format(1_500); // "1s500ms"
format(0); // "0ms"
format(-5_000); // "-5s"Fractional input is rounded to the nearest millisecond. Non-finite input throws.
parse(str) -> number (milliseconds)
The inverse of format. Case-insensitive and tolerant of spacing. Understands
d, h, m, s, and ms, plus an optional leading -/+:
parse('2h30m'); // 9000000
parse('2H 30M'); // 9000000 (case + spacing don't matter)
parse('1d4h'); // 100800000
parse('500ms'); // 500
parse('-1m30s'); // -90000
parse('1.5h'); // 5400000 (fractional units allowed)Empty, garbage, or unknown-unit input throws rather than silently
returning 0, so typos surface loudly.
units
The unit sizes in milliseconds are exposed as
units.SECOND / MINUTE / HOUR / DAY / WEEK / MONTH / YEAR for callers who want
the same constants.
Running the tests
One command, no dependencies:
node test/index.test.jsIt exits 0 when all assertions pass (and prints a pass/fail count). The suite
covers past and future phrasing, every threshold band, format⇄parse
round-trips, sub-second inputs, negative/zero durations, and invalid-input
error handling.
License
MIT — see LICENSE.
