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 🙏

© 2024 – Pkg Stats / Ryan Hefner

moment-wrange

v4.0.5

Published

Fancier date ranges for Moment.js

Downloads

8

Readme

moment-wrange

NPM version CircleCI David bitHound Overall Score

Fancier date ranges for Moment.js.

About

This is a fork of moment-range. We forked because there were major changes that our team needed completed in a very quick manor, and we needed to get off of tracking a git repo and use a full on NPM package.

Primary Differences from moment-range v3.0.3 (forked release)

  • codebase converted from ES6 to ES5
    • broke out functions into individual files
  • tests default to server-side testing (browser testing maintained)
  • better follows the conventions used by moment.js for function signatures
    • new functions have dropped the exclusive option for the inclusivity string that moment introduced in version 2.13.0
    • new functions include access to the units of time for additional granularity
  • Methods Added:
    • add() allows both adjacent and overlapping inputs
    • invertRanges() returns inverse of given ranges for all time
    • isRange() determines whether an object is typeof MomentWrange
    • mergeRanges() collapses an array of ranges into a minimal set
  • many little cleanup items included

Installation

moment-wrange works in both the browser and node.js.

Node / NPM

Install via npm:

npm install --save moment-wrange

ES6:

import Moment from 'moment';
import { extendMoment } from 'moment-wrange';

const moment = extendMoment(Moment);

CommonJS:

const { extendMoment } = require('moment-wrange');
const moment = extendMoment(require('moment'));

Browser

<script src="moment.js"></script>
<script src="moment-wrange.js"></script>
window['moment-wrange'].extendMoment(moment);

Examples

Create

Create a date range:

const start = new Date(2012, 0, 15);
const end   = new Date(2012, 4, 23);
const range = moment.range(start, end);

You can also create a date range with moment objects:

const start = moment('2011-04-15', 'YYYY-MM-DD');
const end   = moment('2011-11-27', 'YYYY-MM-DD');
const range = moment.range(start, end);

Arrays work too:

const dates = [moment('2011-04-15', 'YYYY-MM-DD'), moment('2011-11-27', 'YYYY-MM-DD')];
const range = moment.range(dates);

You can also create a range from an ISO 8601 time interval string:

const timeInterval = '2015-01-17T09:50:04+00:00/2015-04-17T08:29:55+00:00';
const range = moment.range(timeInterval);

You can also create a range from the start until the end of a named interval:

const date = moment('2011-04-15', 'YYYY-MM-DD');
const range = date.range('month');

You can also create open-ended ranges which go to the earliest or latest possible date:

const rangeUntil = moment.range(null, '2011-05-05');
const rangeFrom = moment.range('2011-03-05', null);
const rangeAllTime = moment.range(null, null);

Note: Dates and moment objects both use a timestamp of 00:00:000 if none is provided. To ensure your range includes any timestamp for the given end date, use .setHours(23,59,59,999) when constructing a Date object, or .endOf('day') when constructing a moment object.

Attributes

You can access the start and end moments of the range easily enough:

const start = new Date(2012, 0, 15);
const end   = new Date(2012, 4, 23);
const range = moment.range(start, end);

range.start  // moment
range.end  // moment

Querying

Adjacent

Check if two ranges are touching but not overlapping:

const a = moment('2016-03-15');
const b = moment('2016-03-29');
const c = moment('2016-03-10');
const d = moment('2016-03-15');

const range1 = moment.range(a, b);
const range2 = moment.range(c, d);

range1.adjacent(range2) // true

Center

Calculate the center of a range:

const start = new Date(2011, 2, 5);
const end   = new Date(2011, 3, 5);
const dr    = moment.range(start, end);

dr.center(); // 1300622400000

Contains

Check to see if your range contains a date/moment:

const start  = new Date(2012, 4, 1);
const end    = new Date(2012, 4, 23);
const lol    = new Date(2012, 4, 15);
const wat    = new Date(2012, 4, 27);
const range  = moment.range(start, end);
const range2 = moment.range(lol, wat);

range.contains(lol); // true
range.contains(wat); // false

The exclusive options is used to indicate if the end of the range should be excluded when testing for inclusion:

range.contains(end) // true
range.contains(end, { exclusive: false }) // true
range.contains(end, { exclusive: true }) // false

Intersect

What are the intersecting ranges?

range.intersect(range2); // [moment.range(lol, end)]

IsRange

Is this a MomentWrange object?

moment.isRange(range2); // true

Overlaps

Does it overlap another range?

range.overlaps(range2); // true

Include adjacent ranges:

const a = moment('2016-03-15');
const b = moment('2016-03-20');
const c = moment('2016-03-20');
const d = moment('2016-03-25');

const range1 = moment.range(a, b);
const range2 = moment.range(c, d);

range1.overlaps(range2)                      // false
range1.overlaps(range2, { adjacent: false }) // false
range1.overlaps(range2, { adjacent: true })  // true

Within

Find out if your moment falls within a date range:

const start = new Date(2012, 4, 1);
const end   = new Date(2012, 4, 23);
const when  = moment('2012-05-10', 'YYYY-MM-DD');
const range = moment.range(start, end);

when.within(range); // true

Manipulation

Add

Add/combine/merge adjacent or overlapping ranges.

range.add(range2); // [moment.range(start, d)]

const range3 = moment.range(new Date(2012, 3, 1), new Date(2012, 3, 15);
range.add(range3); // [null]

Clone

Deep clone a range

const start = new Date(2011, 2, 5);
const end   = new Date(2011, 3, 5);
const dr    = moment.range(start, end);

const dr2 = dr.clone();
dr2.start.add(2, 'days');

dr2.start.toDate() === dr.start.toDate() // false

Invert

The inverse ranges for all time.

moment().invertRanges(range2); // [moment.range(null, c), moment.range(d, null)]

Merge

Collapses an array of ranges into the minimal set of non-overlapping and non-adjacent ranges.

const r1 = moment.range('2000-01-01', '2000-06-01');
const r2 = moment.range('2000-02-01', '2000-12-01');
const r3 = moment.range('2001-01-01', '2001-06-01');
const r4 = moment.range('2001-06-01', '2001-07-01');
moment().mergeRanges([r1, r2, r3, r4]); // [moment.range('2000-01-01', '2000-12-01'), moment.range('2001-01-01', '2001-07-01')]

Subtract

Subtracting one range from another.

range.subtract(range2); // [moment.range(c, d)]

Iteration

Each of the iteration methods return an Iterable, providing a convenient and performant interface to iterating over your ranges by a given period.

by

Iterate over your range by a given period. Any of the units accepted by moment.js' add method may be used. E.g.: 'years' | 'quarters' | 'months' | 'weeks' | 'days' | 'hours' | 'minutes' | 'seconds' | 'milliseconds'

const range = moment.range('2010-01-01', '2015-01-01');

for (let month of range.by('month')) {
  month.format('YYYY-MM-DD');
}

const years = Array.from(range.by('year'));
years.length == 5 // true
years.map(m => m.format('YYYY')) // ['2010', '2011', '2012', '2013', '2014', '2015']

Iteration also supports excluding the end value of the range by setting the exclusive option to true.

const start  = new Date(2012, 2, 1);
const end    = new Date(2012, 2, 5);
const range1 = moment.range(start, end);

const acc = Array.from(range1.by('day', { exclusive: true }));

acc.length == 4 // true

Additionally it's possible to iterate by a given step that defaults to 1:

const start  = new Date(2012, 2, 2);
const end    = new Date(2012, 2, 6);
const range1 = moment.range(start, end);

let acc = Array.from(range1.by('day', { step: 2 }));

acc.map(m => m.format('DD')) // ['02', '04', '06']

acc = Array.from(range1.by('day', { exclusive: true, step: 2 }));

acc.map(m => m.format('DD')) // ['02', '04']

byRange

const start = new Date(2012, 2, 1);
const two   = new Date(2012, 2, 2);
const end   = new Date(2012, 2, 5);
const range1 = moment.range(start, end);
const range2 = moment.range(start, two); // One day

Iterate by another range:

const acc = Array.from(range1.by(range2));

acc.length == 5 // true

Exclude the end value:

const acc = Array.from(range1.by(range2, { exclusive: true }));

acc.length == 4 // true

By step:

let acc = Array.from(range1.by(range2, { step: 2 }));

acc.map(m => m.format('DD')) // ['01', '03', '05']

acc = Array.from(range1.by(range2, { exlusive, true, step: 2 }));

acc.map(m => m.format('DD')) // ['01', '03']

reverseBy

Iterate over a range in reverse:

const range = moment.range('2012-01-01', '2015-01-01');
const acc = Array.from(range.reverseBy('years'));
acc.map(m => m.format('YYYY')) // ['2015', '2014', '2013', '2012']

Exclude the end value:

const range = moment.range('2012-01-01', '2015-01-01');
const acc = Array.from(range.reverseBy('years', { exclusive: true }));
acc.map(m => m.format('YYYY')) // ['2015', '2014', '2013']

By step:

const start  = new Date(2012, 2, 2);
const end    = new Date(2012, 2, 6);
const range1 = moment.range(start, end);

let acc = Array.from(range1.reverseBy('day', { step: 2 }));

acc.map(m => m.format('DD')) // ['06', '04', '02']

acc = Array.from(range1.reverseBy('day', { exclusive: true, step: 2 }));

acc.map(m => m.format('DD')) // ['06', '04']

reverseByRange

const start = new Date(2012, 2, 1);
const two   = new Date(2012, 2, 2);
const end   = new Date(2012, 2, 5);
const range1 = moment.range(start, end);
const range2 = moment.range(start, two); // One day

Iterate by another range in reverse:

const acc = Array.from(range1.by(range2));

acc.length == 5 // true
acc.map(m => m.format('DD')) // ['05', '04', '03', '02', '01']

Exclude the end value:

const acc = Array.from(range1.by(range2, { exclusive: true }));

acc.length == 4 // true
acc.map(m => m.format('DD')) // ['05', '04', '03', '02']

By step:

let acc = Array.from(range1.reverseByRange(range2, { step: 2 }));

acc.map(m => m.format('DD')) // ['05', '03', '01']

acc = Array.from(range1.reverseByRange(range2, { exlusive, true, step: 2 }));

acc.map(m => m.format('DD')) // ['05', '03']

Compare

Compare range lengths or add them together with simple math:

const range1 = moment.range(new Date(2011, 2, 5), new Date(2011, 3, 15));
const range2 = moment.range(new Date(1995, 0, 1), new Date(1995, 12, 25));

range2 > range1 // true

range1 + range2 // duration of both ranges in milliseconds

Math.abs(range1 - range2); // difference of ranges in milliseconds

Equality

Check if two ranges are the same, i.e. their starts and ends are the same:

const range1 = moment.range(new Date(2011, 2, 5), new Date(2011, 3, 15));
const range2 = moment.range(new Date(2011, 2, 5), new Date(2011, 3, 15));
const range3 = moment.range(new Date(2011, 3, 5), new Date(2011, 6, 15));

range1.isSame(range2); // true
range2.isSame(range3); // false

range1.isEqual(range2); // true
range2.isEqual(range3); // false

Difference

The difference of the entire range given various units.

Any of the units accepted by moment.js' add method may be used.

const start = new Date(2011, 2, 5);
const end   = new Date(2011, 5, 5);
const dr    = moment.range(start, end);

dr.diff('months'); // 3
dr.diff('days');   // 92
dr.diff();         // 7945200000

Optionally you may specify if the difference should be rounded, by default it mimics moment-js' behaviour and rounds the values:

const d1 = new Date(Date.UTC(2011, 4, 1));
const d2 = new Date(Date.UTC(2011, 4, 5, 12));
const range = moment.range(d1, d2);

dr.diff('days')        // 4
dr.diff('days', false) // 4
dr.diff('days', true)  // 4.5

#duration is an alias for #diff and they may be used interchangeably.

Conversion

toDate

Converts the DateRange to an Array of the start and end Date objects.

const start = new Date(2011, 2, 5);
const end   = new Date(2011, 5, 5);
const dr    = moment.range(start, end);

dr.toDate(); // [new Date(2011, 2, 5), new Date(2011, 5, 5)]

toString

Converting a DateRange to a String will format it as an ISO 8601 time interval:

const start = '2015-01-17T09:50:04+00:00';
const end   = '2015-04-17T08:29:55+00:00';
const range = moment.range(moment.utc(start), moment.utc(end));

range.toString() // '2015-01-17T09:50:04+00:00/2015-04-17T08:29:55+00:00'

valueOf

The difference between the end date and start date in milliseconds.

const start = new Date(2011, 2, 5);
const end   = new Date(2011, 5, 5);
const range = moment.range(start, end);

range.valueOf(); // 7945200000

Running Tests

Clone:

git clone https://[email protected]/theroller/moment-wrange.git

Install the dependencies:

npm install

Do all the things!

npm run test
npm run test:browser
npm run lint

Contributors

License

moment-wrange uses the MIT License.