Socket
Socket
Sign inDemoInstall

moment-range

Package Overview
Dependencies
10
Maintainers
5
Versions
35
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

    moment-range

Fancy date ranges for Moment.js


Version published
Weekly downloads
234K
decreased by-22.33%
Maintainers
5
Install size
975 kB
Created
Weekly downloads
 

Changelog

Source

[3.1.1]

Fixed

  • Fixed intersection rules for zero-length ranges on start/end boundaries

Readme

Source

moment-range CircleCI

Fancy date ranges for Moment.js.

Hey there! After 5 months of inactivity, we're reviewing pull requests and issues to bring moment-range up to date. Get in touch with us in this thread if you have any feedback.

Installation

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

Node / NPM

Install via npm:

npm install --save moment-range

ES6:

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

const moment = extendMoment(Moment);

CommonJS:

const Moment = require('moment');
const MomentRange = require('moment-range');

const moment = MomentRange.extendMoment(Moment);

Browser

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

Thanks to the fine people at cdnjs, you can link to moment-range from the cdnjs servers.

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');
const rangeAllTime = moment.range();

Note that any falsy value except 0 is treated as a missing date, resulting in an open-ended range.

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.

rangeFromInterval

You can also create a range between an interval and a specified date. This accepts positive or negative values for count and the date will default to now if not provided.

const interval = 'month';
const count = 4;
const date = moment('2017-07-20');

const range1 = moment.rangeFromInterval(interval, count, date);  // moment.range('2017-07-20', '2017-11-20')
const range2 = moment.rangeFromInterval('month', -2, date);      // moment.range('2017-05-20', '2017-07-20')

Note: The date can be provided as a Date, String, or Moment. When using a negative interval, the date provided will be set as the end of the range.

parseZoneRange

Parses an ISO 8601 time interval into a date range while preserving the time zones using moment.parseZone.

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

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

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

Many of the following examples make use of these moments:

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

Check if two ranges are touching but not overlapping:


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

range1.adjacent(range2) // true
range1.adjacent(range3) // false
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 range  = moment.range(a, c);

range.contains(b); // true
range.contains(d); // false

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

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

Find out if your moment falls within a date range:

const range = moment.range(a, c);

b.within(range); // true
Overlaps

Does it overlap another range?

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

Include adjacent ranges:

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

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

What is the intersecting range?

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

Is it a Range?

moment.isRange(range); // true
moment.isRange(IamNotRange); // false

Manipulation

Add

Add/combine/merge overlapping or adjacent ranges.

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

const range3 = moment.range(a, b);
const range4 = moment.range(c, d);
range3.add(range4); // null

Include adjacent ranges:

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

range1.add(range2); // null
range1.add(range2, { adjacent: false }); // null
range1.add(range2, { adjacent: true }); // moment.range(a, c)
Clone

Deep clone a range

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

const range2 = range1.clone();
range2.start.add(2, 'days');

range1.start.toDate().getTime() === range2.start.toDate().getTime() // false
Subtract

Subtracting one range from another.

const range_ab = moment.range(a, b);
const range_bc = moment.range(b, c);
const range_cd = moment.range(c, d);
const range_ad = moment.range(a, d);
range_ad.subtract(range_bc); // [moment.range(a, b) moment.range(c, d)]
range_ac.subtract(range_bc); // [moment.range(a, b)]
range_ab.subtract(range_cd); // [moment.range(a, b)]
range_bc.subtract(range_bd); // [null]

Iteration

Each of the iteration methods returns 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 this bad boy:

git clone https://git@github.com/rotaready/moment-range.git

Install the dependencies:

yarn install

Do all the things!

yarn run test
yarn run lint

Contributors

License

moment-range is UNLICENSED.

FAQs

Last updated on 19 Jan 2018

Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc