diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2a65b1367e..78662c17a1 100755
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -761,6 +761,9 @@ for the list of changes made since `v2.0.0-alpha.1`.
- [Add new function `differenceInBusinessDays`](https://github.com/date-fns/date-fns/pull/1194)
which calculates the difference in business days. Kudos to [@ThorrStevens](https://github.com/ThorrStevens)!
+- [Add new function `addBusinessDays`](https://github.com/date-fns/date-fns/pull/1154),
+ similar to `addDays` but ignoring weekends. Thanks to [@ThorrStevens](https://github.com/ThorrStevens)!
+
## [1.30.1] - 2018-12-10
### Fixed
diff --git a/scripts/test/dst.sh b/scripts/test/dst.sh
index 5c756d2bf5..2c8b198168 100755
--- a/scripts/test/dst.sh
+++ b/scripts/test/dst.sh
@@ -11,3 +11,4 @@ export PATH="$(yarn bin):$PATH"
env TZ=America/Sao_Paulo babel-node ./test/dst/parseISO/basic.js
env TZ=Pacific/Apia babel-node ./test/dst/parseISO/samoa.js
env TZ=Asia/Damascus babel-node ./test/dst/eachDayOfInterval/basic.js
+env TZ=America/Santiago babel-node ./test/dst/addBusinessDays/basic.js
diff --git a/src/addBusinessDays/index.d.ts b/src/addBusinessDays/index.d.ts
new file mode 100644
index 0000000000..b1c084e3cd
--- /dev/null
+++ b/src/addBusinessDays/index.d.ts
@@ -0,0 +1,4 @@
+// This file is generated automatically by `scripts/build/typings.js`. Please, don't change it.
+
+import { addBusinessDays } from 'date-fns'
+export default addBusinessDays
diff --git a/src/addBusinessDays/index.js b/src/addBusinessDays/index.js
new file mode 100644
index 0000000000..4f0aa323d5
--- /dev/null
+++ b/src/addBusinessDays/index.js
@@ -0,0 +1,44 @@
+import isWeekend from '../isWeekend/index.js'
+import toDate from '../toDate/index.js'
+import toInteger from '../_lib/toInteger/index.js'
+
+/**
+ * @name addBusinessDays
+ * @category Day Helpers
+ * @summary Add the specified number of business days (mon - fri) to the given date.
+ *
+ * @description
+ * Add the specified number of business days (mon - fri) to the given date, ignoring weekends.
+ *
+ * @param {Date|Number} date - the date to be changed
+ * @param {Number} amount - the amount of business days to be added
+ * @returns {Date} the new date with the business days added
+ * @throws {TypeError} 2 arguments required
+ *
+ * @example
+ * // Add 10 business days to 1 September 2014:
+ * var result = addBusinessDays(new Date(2014, 8, 1), 10)
+ * //=> Mon Sep 15 2014 00:00:00 (skipped weekend days)
+ */
+export default function addBusinessDays(dirtyDate, dirtyAmount) {
+ if (arguments.length < 2) {
+ throw new TypeError(
+ '2 arguments required, but only ' + arguments.length + ' present'
+ )
+ }
+
+ var date = toDate(dirtyDate)
+ var amount = toInteger(dirtyAmount)
+
+ if (isNaN(amount)) return new Date(NaN)
+
+ var hours = date.getHours()
+ var numWeekDays = 0
+ while (numWeekDays < amount) {
+ date.setDate(date.getDate() + 1)
+ date.setHours(hours)
+ if (!isWeekend(date)) numWeekDays++
+ }
+
+ return date
+}
diff --git a/src/addBusinessDays/index.js.flow b/src/addBusinessDays/index.js.flow
new file mode 100644
index 0000000000..3a0eb45a59
--- /dev/null
+++ b/src/addBusinessDays/index.js.flow
@@ -0,0 +1,38 @@
+// @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: (date: Date | number, amount: number) => Date
diff --git a/src/addBusinessDays/test.js b/src/addBusinessDays/test.js
new file mode 100644
index 0000000000..2b90008fb3
--- /dev/null
+++ b/src/addBusinessDays/test.js
@@ -0,0 +1,49 @@
+// @flow
+/* eslint-env mocha */
+
+import assert from 'power-assert'
+import addBusinessDays from '.'
+
+describe('addBusinessDays', function() {
+ it('adds the given number of business days', function() {
+ var result = addBusinessDays(new Date(2014, 8 /* Sep */, 1), 10)
+ assert.deepEqual(result, new Date(2014, 8 /* Sep */, 15))
+ })
+
+ it('accepts a timestamp', function() {
+ var result = addBusinessDays(new Date(2014, 8 /* Sep */, 1).getTime(), 10)
+ assert.deepEqual(result, new Date(2014, 8 /* Sep */, 15))
+ })
+
+ it('converts a fractional number to an integer', function() {
+ var result = addBusinessDays(new Date(2014, 8 /* Sep */, 1), 10.5)
+ assert.deepEqual(result, new Date(2014, 8 /* Sep */, 15))
+ })
+
+ it('implicitly converts number arguments', function() {
+ // $ExpectedMistake
+ var result = addBusinessDays(new Date(2014, 8 /* Sep */, 1), '10')
+ assert.deepEqual(result, new Date(2014, 8 /* Sep */, 15))
+ })
+
+ it('does not mutate the original date', function() {
+ var date = new Date(2014, 8 /* Sep */, 1)
+ addBusinessDays(date, 11)
+ assert.deepEqual(date, new Date(2014, 8 /* Sep */, 1))
+ })
+
+ it('returns `Invalid Date` if the given date is invalid', function() {
+ var result = addBusinessDays(new Date(NaN), 10)
+ assert(result instanceof Date && isNaN(result))
+ })
+
+ it('returns `Invalid Date` if the given amount is NaN', function() {
+ var result = addBusinessDays(new Date(2014, 8 /* Sep */, 1), NaN)
+ assert(result instanceof Date && isNaN(result))
+ })
+
+ it('throws TypeError exception if passed less than 2 arguments', function() {
+ assert.throws(addBusinessDays.bind(null), TypeError)
+ assert.throws(addBusinessDays.bind(null, 1), TypeError)
+ })
+})
diff --git a/src/esm/fp/index.js b/src/esm/fp/index.js
index 2d6a5016ee..fdf8246627 100644
--- a/src/esm/fp/index.js
+++ b/src/esm/fp/index.js
@@ -1,5 +1,6 @@
// This file is generated automatically by `scripts/build/indices.js`. Please, don't change it.
+export { default as addBusinessDays } from './addBusinessDays/index.js'
export { default as addDays } from './addDays/index.js'
export { default as addHours } from './addHours/index.js'
export { default as addISOWeekYears } from './addISOWeekYears/index.js'
diff --git a/src/esm/index.js b/src/esm/index.js
index 4f2c2ed493..837ff003ca 100644
--- a/src/esm/index.js
+++ b/src/esm/index.js
@@ -1,5 +1,6 @@
// This file is generated automatically by `scripts/build/indices.js`. Please, don't change it.
+export { default as addBusinessDays } from './addBusinessDays/index.js'
export { default as addDays } from './addDays/index.js'
export { default as addHours } from './addHours/index.js'
export { default as addISOWeekYears } from './addISOWeekYears/index.js'
diff --git a/src/fp/addBusinessDays/index.d.ts b/src/fp/addBusinessDays/index.d.ts
new file mode 100644
index 0000000000..dd3b8696a7
--- /dev/null
+++ b/src/fp/addBusinessDays/index.d.ts
@@ -0,0 +1,4 @@
+// This file is generated automatically by `scripts/build/typings.js`. Please, don't change it.
+
+import { addBusinessDays } from 'date-fns/fp'
+export default addBusinessDays
diff --git a/src/fp/addBusinessDays/index.js b/src/fp/addBusinessDays/index.js
new file mode 100644
index 0000000000..e1f14a0215
--- /dev/null
+++ b/src/fp/addBusinessDays/index.js
@@ -0,0 +1,8 @@
+// This file is generated automatically by `scripts/build/fp.js`. Please, don't change it.
+
+import fn from '../../addBusinessDays/index.js'
+import convertToFP from '../_lib/convertToFP/index.js'
+
+var addBusinessDays = convertToFP(fn, 2)
+
+export default addBusinessDays
diff --git a/src/fp/addBusinessDays/index.js.flow b/src/fp/addBusinessDays/index.js.flow
new file mode 100644
index 0000000000..03e03ee8c0
--- /dev/null
+++ b/src/fp/addBusinessDays/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: A) => R
+
+type CurriedFn2 = (
+ a: A
+) => CurriedFn1 | ((a: A, b: B) => R)
+
+declare module.exports: CurriedFn2
diff --git a/src/fp/index.js b/src/fp/index.js
index 261e022c14..e2741dc8c2 100644
--- a/src/fp/index.js
+++ b/src/fp/index.js
@@ -3,6 +3,7 @@
var constants = require('../constants/index.js')
module.exports = {
+ addBusinessDays: require('./addBusinessDays/index.js'),
addDays: require('./addDays/index.js'),
addHours: require('./addHours/index.js'),
addISOWeekYears: require('./addISOWeekYears/index.js'),
diff --git a/src/fp/index.js.flow b/src/fp/index.js.flow
index 4fd6141bf9..ceb51ccd26 100644
--- a/src/fp/index.js.flow
+++ b/src/fp/index.js.flow
@@ -66,6 +66,7 @@ type CurriedFn4 = (
) => CurriedFn1 | ((a: A, b: B, c: C, d: D) => R)))
declare module.exports: {
+ addBusinessDays: CurriedFn2,
addDays: CurriedFn2,
addHours: CurriedFn2,
addISOWeekYears: CurriedFn2,
diff --git a/src/index.js b/src/index.js
index 2ae1382dae..14756b4579 100644
--- a/src/index.js
+++ b/src/index.js
@@ -3,6 +3,7 @@
var constants = require('./constants/index.js')
module.exports = {
+ addBusinessDays: require('./addBusinessDays/index.js'),
addDays: require('./addDays/index.js'),
addHours: require('./addHours/index.js'),
addISOWeekYears: require('./addISOWeekYears/index.js'),
diff --git a/src/index.js.flow b/src/index.js.flow
index 53f5aaf286..12ef492dd0 100644
--- a/src/index.js.flow
+++ b/src/index.js.flow
@@ -36,6 +36,8 @@ type Locale = {
}
declare module.exports: {
+ addBusinessDays: (date: Date | number, amount: number) => Date,
+
addDays: (date: Date | number, amount: number) => Date,
addHours: (date: Date | number, amount: number) => Date,
diff --git a/test/dst/addBusinessDays/basic.js b/test/dst/addBusinessDays/basic.js
new file mode 100644
index 0000000000..c55a6860e6
--- /dev/null
+++ b/test/dst/addBusinessDays/basic.js
@@ -0,0 +1,18 @@
+// This is basic DST test for addBusinessDays
+
+import assert from 'assert'
+import addBusinessDays from '../../../src/addBusinessDays'
+
+if (process.env.TZ !== 'America/Santiago')
+ throw new Error('The test must be run with TZ=America/Santiago')
+
+if (parseInt(process.version.match(/^v(\d+)\./)[1]) < 10)
+ throw new Error('The test must be run on Node.js version >= 10')
+
+console.log(addBusinessDays(new Date(2014, 8 /* Sep */, 1), 10).toString())
+
+assert.deepEqual(
+ // new Date(2014, 8, 7) is the DST day
+ addBusinessDays(new Date(2014, 8 /* Sep */, 1), 10).toString(),
+ 'Mon Sep 15 2014 00:00:00 GMT-0300 (Chile Summer Time)'
+)
diff --git a/typings.d.ts b/typings.d.ts
index 1318494fe0..611eea81ec 100644
--- a/typings.d.ts
+++ b/typings.d.ts
@@ -73,6 +73,9 @@ declare module 'date-fns' {
// Regular Functions
declare module 'date-fns' {
+ function addBusinessDays(date: Date | number, amount: number): Date
+ namespace addBusinessDays {}
+
function addDays(date: Date | number, amount: number): Date
namespace addDays {}
@@ -800,6 +803,11 @@ declare module 'date-fns' {
const minTime: number
}
+declare module 'date-fns/addBusinessDays' {
+ import { addBusinessDays } from 'date-fns'
+ export default addBusinessDays
+}
+
declare module 'date-fns/addDays' {
import { addDays } from 'date-fns'
export default addDays
@@ -1580,6 +1588,11 @@ declare module 'date-fns/toDate' {
export default toDate
}
+declare module 'date-fns/addBusinessDays/index' {
+ import { addBusinessDays } from 'date-fns'
+ export default addBusinessDays
+}
+
declare module 'date-fns/addDays/index' {
import { addDays } from 'date-fns'
export default addDays
@@ -2360,6 +2373,11 @@ declare module 'date-fns/toDate/index' {
export default toDate
}
+declare module 'date-fns/addBusinessDays/index.js' {
+ import { addBusinessDays } from 'date-fns'
+ export default addBusinessDays
+}
+
declare module 'date-fns/addDays/index.js' {
import { addDays } from 'date-fns'
export default addDays
@@ -3143,6 +3161,9 @@ declare module 'date-fns/toDate/index.js' {
// FP Functions
declare module 'date-fns/fp' {
+ const addBusinessDays: CurriedFn2
+ namespace addBusinessDays {}
+
const addDays: CurriedFn2
namespace addDays {}
@@ -3763,6 +3784,11 @@ declare module 'date-fns/fp' {
const minTime: number
}
+declare module 'date-fns/fp/addBusinessDays' {
+ import { addBusinessDays } from 'date-fns/fp'
+ export = addBusinessDays
+}
+
declare module 'date-fns/fp/addDays' {
import { addDays } from 'date-fns/fp'
export = addDays
@@ -4663,6 +4689,11 @@ declare module 'date-fns/fp/toDate' {
export = toDate
}
+declare module 'date-fns/fp/addBusinessDays/index' {
+ import { addBusinessDays } from 'date-fns/fp'
+ export = addBusinessDays
+}
+
declare module 'date-fns/fp/addDays/index' {
import { addDays } from 'date-fns/fp'
export = addDays
@@ -5563,6 +5594,11 @@ declare module 'date-fns/fp/toDate/index' {
export = toDate
}
+declare module 'date-fns/fp/addBusinessDays/index.js' {
+ import { addBusinessDays } from 'date-fns/fp'
+ export = addBusinessDays
+}
+
declare module 'date-fns/fp/addDays/index.js' {
import { addDays } from 'date-fns/fp'
export = addDays
@@ -6466,6 +6502,9 @@ declare module 'date-fns/fp/toDate/index.js' {
// ECMAScript Module Functions
declare module 'date-fns/esm' {
+ function addBusinessDays(date: Date | number, amount: number): Date
+ namespace addBusinessDays {}
+
function addDays(date: Date | number, amount: number): Date
namespace addDays {}
@@ -7193,6 +7232,11 @@ declare module 'date-fns/esm' {
const minTime: number
}
+declare module 'date-fns/esm/addBusinessDays' {
+ import { addBusinessDays } from 'date-fns/esm'
+ export default addBusinessDays
+}
+
declare module 'date-fns/esm/addDays' {
import { addDays } from 'date-fns/esm'
export default addDays
@@ -7973,6 +8017,11 @@ declare module 'date-fns/esm/toDate' {
export default toDate
}
+declare module 'date-fns/esm/addBusinessDays/index' {
+ import { addBusinessDays } from 'date-fns/esm'
+ export default addBusinessDays
+}
+
declare module 'date-fns/esm/addDays/index' {
import { addDays } from 'date-fns/esm'
export default addDays
@@ -8753,6 +8802,11 @@ declare module 'date-fns/esm/toDate/index' {
export default toDate
}
+declare module 'date-fns/esm/addBusinessDays/index.js' {
+ import { addBusinessDays } from 'date-fns/esm'
+ export default addBusinessDays
+}
+
declare module 'date-fns/esm/addDays/index.js' {
import { addDays } from 'date-fns/esm'
export default addDays
@@ -9536,6 +9590,9 @@ declare module 'date-fns/esm/toDate/index.js' {
// ECMAScript Module FP Functions
declare module 'date-fns/esm/fp' {
+ const addBusinessDays: CurriedFn2
+ namespace addBusinessDays {}
+
const addDays: CurriedFn2
namespace addDays {}
@@ -10156,6 +10213,11 @@ declare module 'date-fns/esm/fp' {
const minTime: number
}
+declare module 'date-fns/esm/fp/addBusinessDays' {
+ import { addBusinessDays } from 'date-fns/esm/fp'
+ export default addBusinessDays
+}
+
declare module 'date-fns/esm/fp/addDays' {
import { addDays } from 'date-fns/esm/fp'
export default addDays
@@ -11056,6 +11118,11 @@ declare module 'date-fns/esm/fp/toDate' {
export default toDate
}
+declare module 'date-fns/esm/fp/addBusinessDays/index' {
+ import { addBusinessDays } from 'date-fns/esm/fp'
+ export default addBusinessDays
+}
+
declare module 'date-fns/esm/fp/addDays/index' {
import { addDays } from 'date-fns/esm/fp'
export default addDays
@@ -11956,6 +12023,11 @@ declare module 'date-fns/esm/fp/toDate/index' {
export default toDate
}
+declare module 'date-fns/esm/fp/addBusinessDays/index.js' {
+ import { addBusinessDays } from 'date-fns/esm/fp'
+ export default addBusinessDays
+}
+
declare module 'date-fns/esm/fp/addDays/index.js' {
import { addDays } from 'date-fns/esm/fp'
export default addDays
@@ -14919,6 +14991,8 @@ declare module 'date-fns/esm/locale/zh-TW/index.js' {
// dateFns Global Interface
interface dateFns {
+ addBusinessDays(date: Date | number, amount: number): Date
+
addDays(date: Date | number, amount: number): Date
addHours(date: Date | number, amount: number): Date