Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new feature differenceInBusinessDays #1194

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
410 changes: 210 additions & 200 deletions CHANGELOG.md

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions src/differenceInBusinessDays/index.d.ts
@@ -0,0 +1,4 @@
// This file is generated automatically by `scripts/build/typings.js`. Please, don't change it.

import { differenceInBusinessDays } from 'date-fns'
export default differenceInBusinessDays
62 changes: 62 additions & 0 deletions src/differenceInBusinessDays/index.js
@@ -0,0 +1,62 @@
import compareAsc from '../compareAsc/index.js'
import eachDayOfInterval from '../eachDayOfInterval/index.js'
import isValid from '../isValid/index.js'
import isWeekend from '../isWeekend/index.js'
import toDate from '../toDate/index.js'

/**
* @name differenceInBusinessDays
* @category Day Helpers
* @summary Get the number of business days between the given dates.
*
* @description
* Get the number of business day periods between the given dates.
* Business days being days that arent in the weekend.
* Like `differenceInCalendarDays`, the function removes the times from
* the dates before calculating the difference.
*
* @param {Date|Number} dateLeft - the later date
* @param {Date|Number} dateRight - the earlier date
* @returns {Number} the number of business days
* @throws {TypeError} 2 arguments required
*
* @example
* // How many business days are between
* // 10 January 2014 and 20 July 2014?
* var result = differenceInBusinessDays(
* new Date(2014, 6, 20),
* new Date(2014, 0, 10)
* )
* //=> 136
*/
export default function differenceInBusinessDays(
dirtyDateLeft,
dirtyDateRight
) {
if (arguments.length < 2) {
throw new TypeError(
'2 arguments required, but only ' + arguments.length + ' present'
)
}

var dateLeft = toDate(dirtyDateLeft)
var dateRight = toDate(dirtyDateRight)

if (!isValid(dateLeft) || !isValid(dateRight)) return new Date(NaN)

var sign = compareAsc(dateLeft, dateRight)
var interval =
sign > 0
? { start: dateRight, end: dateLeft }
: { start: dateLeft, end: dateRight }

var daysOfInterval = eachDayOfInterval(interval)
var difference = daysOfInterval.filter(function(day) {
return !isWeekend(day)
})
// Substruct 1 because interval contains both starting and ending dates
var result = sign * (difference.length - 1)

// Prevent negative zero
return result === 0 ? 0 : result
}
41 changes: 41 additions & 0 deletions src/differenceInBusinessDays/index.js.flow
@@ -0,0 +1,41 @@
// @flow
// This file is generated automatically by `scripts/build/typings.js`. Please, don't change it.

type Interval = {
start: Date | number,
end: Date | number
}

type Locale = {
formatDistance: Function,
formatRelative: Function,
localize: {
ordinalNumber: Function,
era: Function,
quarter: Function,
month: Function,
day: Function,
dayPeriod: Function
},
formatLong: Object,
date: Function,
time: Function,
dateTime: Function,
match: {
ordinalNumber: Function,
era: Function,
quarter: Function,
month: Function,
day: Function,
dayPeriod: Function
},
options?: {
weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6,
firstWeekContainsDate?: 1 | 2 | 3 | 4 | 5 | 6 | 7
}
}

declare module.exports: (
dateLeft: Date | number,
dateRight: Date | number
) => number
105 changes: 105 additions & 0 deletions src/differenceInBusinessDays/test.js
@@ -0,0 +1,105 @@
// @flow
/* eslint-env mocha */

import assert from 'power-assert'
import differenceInBusinessDays from '.'

describe('differenceInBusinessDays', function() {
it('returns the number of business days between the given dates, excluding weekends', function() {
var result = differenceInBusinessDays(
new Date(2014, 6 /* Jul */, 20),
new Date(2014, 0 /* Jan */, 10)
)
assert(result === 135)
})

it('returns a negative number if the time value of the first date is smaller', function() {
var result = differenceInBusinessDays(
new Date(2014, 0 /* Jan */, 10),
new Date(2014, 6 /* Jul */, 20)
)
assert(result === -135)
})

it('accepts timestamps', function() {
var result = differenceInBusinessDays(
new Date(2014, 6, 20).getTime(),
new Date(2014, 0, 10).getTime()
)
assert(result === 135)
})

describe('edge cases', function() {
it('the difference is less than a day, but the given dates are in different calendar days', function() {
var result = differenceInBusinessDays(
new Date(2014, 8 /* Sep */, 5, 0, 0),
new Date(2014, 8 /* Sep */, 4, 23, 59)
)
assert(result === 1)
})

it('the same for the swapped dates', function() {
var result = differenceInBusinessDays(
new Date(2014, 8 /* Sep */, 4, 23, 59),
new Date(2014, 8 /* Sep */, 5, 0, 0)
)
assert(result === -1)
})

it('the time values of the given dates are the same', function() {
var result = differenceInBusinessDays(
new Date(2014, 8 /* Sep */, 5, 0, 0),
new Date(2014, 8 /* Sep */, 4, 0, 0)
)
assert(result === 1)
})

it('the given dates are the same', function() {
var result = differenceInBusinessDays(
new Date(2014, 8 /* Sep */, 5, 0, 0),
new Date(2014, 8 /* Sep */, 5, 0, 0)
)
assert(result === 0)
})

it('does not return -0 when the given dates are the same', () => {
function isNegativeZero(x) {
return x === 0 && 1 / x < 0
}

var result = differenceInBusinessDays(
new Date(2014, 8 /* Sep */, 5, 0, 0),
new Date(2014, 8 /* Sep */, 5, 0, 0)
)

var resultIsNegative = isNegativeZero(result)
assert(resultIsNegative === false)
})

it('returns NaN if the first date is `Invalid Date`', function() {
var result = differenceInBusinessDays(
new Date(NaN),
new Date(2017, 0 /* Jan */, 1)
)
assert(isNaN(result))
})

it('returns NaN if the second date is `Invalid Date`', function() {
var result = differenceInBusinessDays(
new Date(2017, 0 /* Jan */, 1),
new Date(NaN)
)
assert(isNaN(result))
})

it('returns NaN if the both dates are `Invalid Date`', function() {
var result = differenceInBusinessDays(new Date(NaN), new Date(NaN))
assert(isNaN(result))
})

it('throws TypeError exception if passed less than 2 arguments', function() {
assert.throws(differenceInBusinessDays.bind(null), TypeError)
assert.throws(differenceInBusinessDays.bind(null, 1), TypeError)
})
})
})
3 changes: 3 additions & 0 deletions src/esm/fp/index.js
Expand Up @@ -17,6 +17,9 @@ export { default as closestIndexTo } from './closestIndexTo/index.js'
export { default as closestTo } from './closestTo/index.js'
export { default as compareAsc } from './compareAsc/index.js'
export { default as compareDesc } from './compareDesc/index.js'
export {
default as differenceInBusinessDays
} from './differenceInBusinessDays/index.js'
export {
default as differenceInCalendarDays
} from './differenceInCalendarDays/index.js'
Expand Down
3 changes: 3 additions & 0 deletions src/esm/index.js
Expand Up @@ -17,6 +17,9 @@ export { default as closestIndexTo } from './closestIndexTo/index.js'
export { default as closestTo } from './closestTo/index.js'
export { default as compareAsc } from './compareAsc/index.js'
export { default as compareDesc } from './compareDesc/index.js'
export {
default as differenceInBusinessDays
} from './differenceInBusinessDays/index.js'
export {
default as differenceInCalendarDays
} from './differenceInCalendarDays/index.js'
Expand Down
4 changes: 4 additions & 0 deletions src/fp/differenceInBusinessDays/index.d.ts
@@ -0,0 +1,4 @@
// This file is generated automatically by `scripts/build/typings.js`. Please, don't change it.

import { differenceInBusinessDays } from 'date-fns/fp'
export default differenceInBusinessDays
8 changes: 8 additions & 0 deletions src/fp/differenceInBusinessDays/index.js
@@ -0,0 +1,8 @@
// This file is generated automatically by `scripts/build/fp.js`. Please, don't change it.

import fn from '../../differenceInBusinessDays/index.js'
import convertToFP from '../_lib/convertToFP/index.js'

var differenceInBusinessDays = convertToFP(fn, 2)

export default differenceInBusinessDays
44 changes: 44 additions & 0 deletions src/fp/differenceInBusinessDays/index.js.flow
@@ -0,0 +1,44 @@
// @flow
// This file is generated automatically by `scripts/build/typings.js`. Please, don't change it.

type Interval = {
start: Date | number,
end: Date | number
}

type Locale = {
formatDistance: Function,
formatRelative: Function,
localize: {
ordinalNumber: Function,
era: Function,
quarter: Function,
month: Function,
day: Function,
dayPeriod: Function
},
formatLong: Object,
date: Function,
time: Function,
dateTime: Function,
match: {
ordinalNumber: Function,
era: Function,
quarter: Function,
month: Function,
day: Function,
dayPeriod: Function
},
options?: {
weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6,
firstWeekContainsDate?: 1 | 2 | 3 | 4 | 5 | 6 | 7
}
}

type CurriedFn1<A, R> = <A>(a: A) => R

type CurriedFn2<A, B, R> = <A>(
a: A
) => CurriedFn1<B, R> | (<A, B>(a: A, b: B) => R)

declare module.exports: CurriedFn2<Date | number, Date | number, number>
1 change: 1 addition & 0 deletions src/fp/index.js
Expand Up @@ -18,6 +18,7 @@ module.exports = {
closestTo: require('./closestTo/index.js'),
compareAsc: require('./compareAsc/index.js'),
compareDesc: require('./compareDesc/index.js'),
differenceInBusinessDays: require('./differenceInBusinessDays/index.js'),
differenceInCalendarDays: require('./differenceInCalendarDays/index.js'),
differenceInCalendarISOWeekYears: require('./differenceInCalendarISOWeekYears/index.js'),
differenceInCalendarISOWeeks: require('./differenceInCalendarISOWeeks/index.js'),
Expand Down
1 change: 1 addition & 0 deletions src/fp/index.js.flow
Expand Up @@ -81,6 +81,7 @@ declare module.exports: {
closestTo: CurriedFn2<(Date | number)[], Date | number, Date>,
compareAsc: CurriedFn2<Date | number, Date | number, number>,
compareDesc: CurriedFn2<Date | number, Date | number, number>,
differenceInBusinessDays: CurriedFn2<Date | number, Date | number, number>,
differenceInCalendarDays: CurriedFn2<Date | number, Date | number, number>,
differenceInCalendarISOWeeks: CurriedFn2<
Date | number,
Expand Down
1 change: 1 addition & 0 deletions src/index.js
Expand Up @@ -18,6 +18,7 @@ module.exports = {
closestTo: require('./closestTo/index.js'),
compareAsc: require('./compareAsc/index.js'),
compareDesc: require('./compareDesc/index.js'),
differenceInBusinessDays: require('./differenceInBusinessDays/index.js'),
differenceInCalendarDays: require('./differenceInCalendarDays/index.js'),
differenceInCalendarISOWeekYears: require('./differenceInCalendarISOWeekYears/index.js'),
differenceInCalendarISOWeeks: require('./differenceInCalendarISOWeeks/index.js'),
Expand Down
5 changes: 5 additions & 0 deletions src/index.js.flow
Expand Up @@ -75,6 +75,11 @@ declare module.exports: {

compareDesc: (dateLeft: Date | number, dateRight: Date | number) => number,

differenceInBusinessDays: (
dateLeft: Date | number,
dateRight: Date | number
) => number,

differenceInCalendarDays: (
dateLeft: Date | number,
dateRight: Date | number
Expand Down