Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
New eachMinuteOfInterval function (#2382)
Added new `eachMinuteOfInterval` function. Co-authored-by: Vitor Ferreira <vitorfrs98@gmail.com>
- Loading branch information
1 parent
988b6ef
commit 76945e0
Showing
3 changed files
with
189 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// @flow | ||
/* eslint-env mocha */ | ||
/* global suite, benchmark */ | ||
|
||
import eachMinuteOfInterval from '.' | ||
|
||
suite( | ||
'eachMinuteOfInterval', | ||
function() { | ||
benchmark('date-fns', function() { | ||
return eachMinuteOfInterval({ start: this.dateA, end: this.dateB }) | ||
}) | ||
}, | ||
{ | ||
setup: function() { | ||
this.dateA = new Date() | ||
this.dateB = new Date(this.dateA.getTime() + 300000) | ||
} | ||
} | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import addMinutes from '../addMinutes/index' | ||
import toDate from '../toDate/index' | ||
import startOfMinute from '../startOfMinute/index' | ||
import requiredArgs from '../_lib/requiredArgs/index' | ||
|
||
import { Interval, StepOptions } from '../types' | ||
|
||
/** | ||
* @name eachMinuteOfInterval | ||
* @category Interval Helpers | ||
* @summary Return the array of minutes within the specified time interval. | ||
* | ||
* @description | ||
* Returns the array of minutes within the specified time interval. | ||
* | ||
* @param {Interval} interval - the interval. See [Interval]{@link https://date-fns.org/docs/Interval} | ||
* @param {Object} [options] - an object with options. | ||
* @param {Number} [options.step=1] - the step to increment by. The starts of minutes from the hour of the interval start to the hour of the interval end | ||
* @throws {TypeError} 1 argument requie value should be more than 1. | ||
* @returns {Date[]} the array withred | ||
* @throws {RangeError} `options.step` must be a number equal or greater than 1 | ||
* @throws {RangeError} The start of an interval cannot be after its end | ||
* @throws {RangeError} Date in interval cannot be `Invalid Date` | ||
* | ||
* @example | ||
* // Each minute between 14 October 2020, 13:00 and 14 October 2020, 13:03 | ||
* const result = eachMinuteOfInterval({ | ||
* start: new Date(2014, 9, 14, 13), | ||
* end: new Date(2014, 9, 14, 13, 3) | ||
* }) | ||
* //=> [ | ||
* // Wed Oct 14 2014 13:00:00, | ||
* // Wed Oct 14 2014 13:01:00, | ||
* // Wed Oct 14 2014 13:02:00, | ||
* // Wed Oct 14 2014 13:03:00 | ||
* // ] | ||
*/ | ||
export default function eachMinuteOfInterval( | ||
interval: Interval, | ||
options?: StepOptions | ||
): Date[] { | ||
requiredArgs(1, arguments) | ||
|
||
const startDate = startOfMinute(toDate(interval.start)) | ||
const endDate = startOfMinute(toDate(interval.end)) | ||
|
||
const startTime = startDate.getTime() | ||
const endTime = endDate.getTime() | ||
|
||
if (startTime >= endTime) { | ||
throw new RangeError('Invalid interval') | ||
} | ||
|
||
const dates = [] | ||
|
||
let currentDate = startDate | ||
|
||
const step = options && 'step' in options ? Number(options.step) : 1 | ||
if (step < 1 || isNaN(step)) | ||
throw new RangeError( | ||
'`options.step` must be a number equal or greater than 1' | ||
) | ||
|
||
while (currentDate.getTime() <= endTime) { | ||
dates.push(toDate(currentDate)) | ||
currentDate = addMinutes(currentDate, step) | ||
} | ||
|
||
return dates | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
// @flow | ||
/* eslint-env mocha */ | ||
|
||
import assert from 'power-assert' | ||
|
||
import eachMinuteOfInterval from '.' | ||
|
||
describe('eachMinuteOfInterval', () => { | ||
it('should return an array of Date objects containing a Date for each minute between the interval', () => { | ||
const result = eachMinuteOfInterval({ | ||
start: new Date(2020, 10, 14, 13, 0), | ||
end: new Date(2020, 10, 14, 13, 5) | ||
}) | ||
|
||
assert.deepEqual(result, [ | ||
new Date(2020, 10, 14, 13, 0), | ||
new Date(2020, 10, 14, 13, 1), | ||
new Date(2020, 10, 14, 13, 2), | ||
new Date(2020, 10, 14, 13, 3), | ||
new Date(2020, 10, 14, 13, 4), | ||
new Date(2020, 10, 14, 13, 5) | ||
]) | ||
}) | ||
|
||
it('should handle all the minutes that are not in the begining', () => { | ||
const result = eachMinuteOfInterval({ | ||
start: new Date(2020, 10, 14, 13, 0, 33), | ||
end: new Date(2020, 10, 14, 13, 2) | ||
}) | ||
|
||
assert.deepEqual(result[0], new Date(2020, 10, 14, 13)) | ||
assert.deepEqual(result[2], new Date(2020, 10, 14, 13, 2)) | ||
}) | ||
|
||
it('should accept timestamps', () => { | ||
const start = new Date(2020, 10, 14, 13, 0).getTime() | ||
const end = new Date(2020, 10, 14, 13, 2).getTime() | ||
|
||
const result = eachMinuteOfInterval({ | ||
start, | ||
end | ||
}) | ||
|
||
assert.deepEqual(result, [ | ||
new Date(2020, 10, 14, 13, 0), | ||
new Date(2020, 10, 14, 13, 1), | ||
new Date(2020, 10, 14, 13, 2) | ||
]) | ||
}) | ||
|
||
it('throws an exception if the start date is after the end date', () => { | ||
const block = eachMinuteOfInterval.bind(null, { | ||
start: new Date(2014, 10, 14, 10), | ||
end: new Date(2014, 10, 14, 5) | ||
}) | ||
assert.throws(block, RangeError) | ||
}) | ||
|
||
describe('options.step', () => { | ||
const interval = { | ||
start: new Date(2020, 9, 14, 13, 1), | ||
end: new Date(2020, 9, 14, 13, 7) | ||
} | ||
|
||
const stepError = /^RangeError: `options.step` must be a number equal or greater than 1$/ | ||
|
||
it('returns an array with starts of hours from the hour of the start date to the hour of the end date with the given step', () => { | ||
const result = eachMinuteOfInterval(interval, { step: 3 }) | ||
assert.deepEqual(result, [ | ||
new Date(2020, 9, 14, 13, 1), | ||
new Date(2020, 9, 14, 13, 4), | ||
new Date(2020, 9, 14, 13, 7) | ||
]) | ||
}) | ||
|
||
it('throws TypeError error if `options.step` is less than 1', () => { | ||
assert.throws( | ||
() => eachMinuteOfInterval(interval, { step: 0 }), | ||
stepError | ||
) | ||
assert.throws( | ||
() => eachMinuteOfInterval(interval, { step: -3 }), | ||
stepError | ||
) | ||
}) | ||
|
||
it('throws TypeError error if `options.step` is NaN', () => { | ||
// $ExpectedMistake | ||
assert.throws( | ||
() => eachMinuteOfInterval(interval, { step: 'w' }), | ||
stepError | ||
) | ||
assert.throws( | ||
() => eachMinuteOfInterval(interval, { step: NaN }), | ||
stepError | ||
) | ||
}) | ||
}) | ||
}) |