@kovalenko/datemath
v1.0.3
Published
A lightweight elasticsearch-style date math parser built on [Luxon](https://moment.github.io/luxon/) instead of moment.js. Works in both Node.js (NestJS, etc.) and the browser.
Maintainers
Readme
@kovalenko/datemath
A lightweight elasticsearch-style date math parser built on Luxon instead of moment.js. Works in both Node.js (NestJS, etc.) and the browser.
Install
npm install @kovalenko/datemath luxon
# or
pnpm add @kovalenko/datemath luxonluxon is a peer/runtime dependency — make sure it's installed alongside.
Why
moment.js is in maintenance mode and adds noticeable bundle weight. This package reimplements the familiar elasticsearch date-math syntax (now-1d/d, now+5m, ISO date + || math, etc.) on top of Luxon, which is tree-shakeable, immutable by design, and has first-class timezone support via Intl.
Quick start
import { parse } from '@kovalenko/datemath';
parse('now').toISO(); // current time
parse('now-1d').toISO(); // 24 hours ago
parse('now-1d/d').toISO(); // start of yesterday (00:00:00)
parse('now-1d/d+14h').toISO(); // yesterday at 14:00
parse('2024-01-01||+1M/d').toISO(); // 2024-02-01, start of dayparse() always returns a Luxon DateTime. On invalid input it returns an invalid DateTime instead of throwing — check with .isValid:
const dt = parse('garbage');
if (!dt.isValid) {
console.log(dt.invalidReason); // e.g. "invalid expression"
}Syntax
| Expression | Meaning |
|---|---|
| now | current time |
| now-1d, now+5m | relative offset: +/- followed by a number and a unit |
| now-1d/d | offset, then round down (/) to the start of the unit |
| now-1d/d with roundUp: true | round up to the end of the unit instead |
| <ISO date> | an absolute ISO8601 timestamp, e.g. 2024-01-01T00:00:00 |
| <ISO date>\|\|<math> | absolute date as the anchor, followed by the same math syntax as above |
You can chain multiple operations: now-1d+12h, now/w+3d.
Units
| Code | Unit |
|---|---|
| ms | millisecond |
| s | second |
| m | minute |
| h | hour |
| d | day |
| w | week |
| M | month |
| y | year |
Note: rounding (/) only accepts a single whole unit — now/d is valid, now/2d is not.
API
parse(text, options?): DateTime
text: string | Date | DateTime— the expression to parse. ADateor an already-valid LuxonDateTimeis returned as-is (wrapped intoDateTimefor a plainDate).options.roundUp?: boolean— round to the end of the unit instead of the start when using/. Defaultfalse.options.forceNow?: Date— use this asnowinstead of the real current time (useful for tests).
Returns a Luxon DateTime, possibly invalid — always check .isValid before relying on the result if the input isn't trusted.
unitsMap, units, unitsAsc, unitsDesc
Exported metadata about the supported unit codes (weights, type, base ms value) — mostly useful if you're building validation or autocomplete on top of the parser.
Differences from @elastic/datemath
- Built on Luxon, not moment — smaller footprint, immutable
DateTime, nativeIntl-based timezone handling. - No
momentInstanceoption (no equivalent concept in Luxon — locale/zone are set on theDateTimeitself). - Invalid input returns an invalid
DateTimerather thanundefined.
Usage in node.js
Works out of the box — the package ships both CJS and ESM builds via conditional exports, so require('@kovalenko/datemath') and import { parse } from '@kovalenko/datemath' both resolve correctly.
Usage in the browser
Same import, no special config needed — the ESM build is picked up automatically by Vite/webpack/etc.
import { parse } from '@kovalenko/datemath';License
MIT
