moment-range

Fancy date ranges for Moment.js — create, query, compare, and iterate over time intervals.

Library
npm
v4.0.2
1,680stars
Unlicense

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
45/100Fair
Development Activity0
Maintenance20
Community72
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
73/100Good
Architecture75
Code Quality78
Innovation55
Learning Curve85

moment-range extends Moment.js with a DateRange type and a set of methods for working with spans of time rather than single points in time. It lets you build a range from two dates, an array, an ISO 8601 time interval string, or a named interval like month or year, then query it for containment, overlap, adjacency, intersection, and difference.

Beyond comparisons, moment-range adds iteration: by and byRange walk a range in fixed steps (every day, every 3 hours, every custom duration), while reverseBy and reverseByRange do the same from the end backwards. Ranges also support set-like operations — add to merge overlapping ranges, subtract to remove one range from another, and snapTo to round a range’s edges out to the nearest interval boundary.

The library ships as a small ES6 class (DateRange) plus a moment.range() factory function attached via extendMoment(moment), so it stays an opt-in extension rather than a Moment.js fork. TypeScript and Flow type definitions are bundled, and a moment.isRange() helper and Moment#within() instance method round out the API for everyday date-range checks.

What You Get

  • A DateRange class supporting construction from two dates, an array, an ISO 8601 interval string, or a named interval (year, month, week, etc.)
  • Query methods — contains, overlaps, intersect, adjacent, isEqual — for comparing ranges and points against a range
  • Iteration methods — by, byRange, reverseBy, reverseByRange — that walk a range in fixed steps using native JS iterators
  • Set-like operations — add to merge overlapping ranges, subtract to remove a range from another, snapTo to round edges to interval boundaries
  • Bundled TypeScript (.d.ts) and Flow (.js.flow) type declarations for type-checked consumption

Common Use Cases

  • Checking whether a given date or timestamp falls inside a booking, subscription, or availability window
  • Detecting overlapping or adjacent date ranges — e.g. conflicting calendar events or reservation periods
  • Generating a list of dates/timestamps at a fixed cadence within a window, such as every day or every hour between a start and end
  • Computing the intersection or difference between two ranges, e.g. the overlapping portion of two employees’ shifts
  • Building calendar or scheduling UIs that need to render, compare, and step through spans of time rather than single dates

Under The Hood

Architecture The entire library lives in one module, lib/moment-range.js, structured around a single DateRange ES6 class plus an extendMoment(moment) function that mixes range-aware statics and instance methods onto a caller-supplied Moment.js instance. DateRange’s constructor normalizes several input shapes (two arguments, a two-element array, or an ISO interval string) into start/end Moment objects, defaulting to the library’s own effectively-infinite sentinel timestamps for open-ended ranges. Every comparison and set operation (contains, intersect, overlaps, subtract, adjacent) is implemented as pure numeric comparisons against .valueOf() millisecond timestamps rather than repeated Moment method calls, which keeps the core logic simple and testable in isolation from Moment’s own API surface. Iteration (by/byRange and their reverse variants) is implemented against the native Symbol.iterator protocol (via the es6-symbol polyfill dependency) so ranges can be consumed directly with for...of or spread syntax; nothing else in the app would break if this abstraction changed, since extendMoment is the sole integration seam with consumer code.

Tech Stack The library targets Moment.js (>= 2) as a peer dependency and depends only on es6-symbol at runtime for iterator-protocol support in older environments. Source is written in ES6/Flow-annotated JavaScript and compiled with Babel (babel-preset-es2015, babel-preset-stage-0) and bundled for distribution with Webpack 2. The published dist/ output includes a UMD-style browser bundle alongside the CommonJS build, and both Flow (flow-bin) and TypeScript (tsc against a typing-tests/ project) type-check the bundled declaration files as part of the pre-release check script.

Code Quality Tests are written with Mocha-style describe/it blocks (via expect.js assertions) and run in real browsers through Karma with the PhantomJS and Chrome launchers; the single test file covers the full public API — constructors, all query/iteration/set methods, edge cases like zero-length and open-ended ranges — in over 1,300 lines, which is extensive for a library this size. Code style is enforced with a project ESLint config (babel-eslint parser) run via yarn lint, and the preversion script chains type-checking, linting, and the test suite before any release, indicating a deliberate quality gate rather than ad hoc publishing. Error handling is minimal by design — the library throws only for explicitly invalid dates in rangeFromInterval and otherwise relies on Moment.js’s own permissive parsing.

What Makes It Unique Rather than inventing a parallel date API, moment-range’s distinguishing choice is making ranges iterable via the standard JS iterator protocol, so a range can be looped with for...of or spread into an array using ordinary language syntax instead of a bespoke .toArray()-style method. Combining that with symmetric forward/backward iteration (by/reverseBy) and interval-based iteration by duration (byRange, using another Moment/duration object as the step rather than a named unit) gives it flexibility most simpler date-range helpers don’t attempt, though the underlying comparison logic itself uses standard interval-arithmetic patterns rather than a genuinely novel algorithm.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search